I am having difficulty trying to implement a constructor for my child class. I understand the purpose of the constructor is to set the states of the class to the values passed? am I correct in this?
I am getting an error;
no matching function for call to 'superclass'
My question is do I have to link my constructor for a child class to the superclass? what is the relationship in terms of constructors between the two classes?
#include<iostream>
using namespace std;
class Buildings
{
private:
float price, area;
string city;
public:
Buildings(float, float, string);
// Buildings(float, float, float);
void virtual display();
void virtual getprice(float);
void virtual getcity(string);
void virtual getarea(float);
};
Buildings::Buildings(float b_price, float b_area, string b_city):price(b_price), area(b_area), city(b_city)
{
}
void Buildings::display()
{
cout<<"The city, price and area(sqft) of the building are: "<<city<<endl<<price<<endl<<area;
}
void Buildings::getprice(float aprice)
{
price = aprice;//potential error handling
}
void Buildings::getarea(float asize)
{
area = asize;
}
void Buildings::getcity(string acity)
{
city = acity;
}
class Apartment:public Buildings
{
private:
float numtennants;
float rent;
float rentpr;
public:
Apartment(float numres, float numrent, float numrentpr);
void virtual display();
void virtual avgrent(float);
void virtual totrent(float);
void virtual totres(float);
};
Apartment::Apartment(float numres, float numrent, float numrentpr):numtennants(numres),rent(numrent),rentpr(numrentpr)
{}
void Apartment::display()
{
Buildings::display();
}
Buildings doesn't have a default constructor. You must explicitly call the only Buildings constructor that exists, passing along the suitable arguments.
If you want do disallow public default-construction of Buildings objects, but allow child-classes to use it, you can make a default constructor that is protected. Like
class Buildings
{
public:
// Public constructor, only way to construct object of this class
// for the general public
Buildings(float, float, string);
// Other public functions...
protected:
// Default constructor, which initializes the private members
// to some suitable values
// Only usable by child-classes
Buildings()
: price(0), area(0), city("")
{}
private:
float price, area;
string city;
};
You must call the parent class's constructor in your child class's member initializer list.
struct A {
A(int a) : a_(a) {}
int a_;
};
struct B : public A {
B(int a, int b) : A(a), b_(b) {}
int b_;
};
Related
So I have a fairly complex programm that I dont whant to go into right now. I will include a toy example of the same process and then go over it in more detail.
In my Programm I encounter the Error constructor for 'Hunter' must explicitly initialize the base class 'WorldObject' which does not have a default constructor with multilevel inheritance: WorldObject -> Creature -> Hunter.
To recreate the same structure I made the following:
class Base
{
protected:
int a;
public:
Base(int a): a(a) { print("Base contructed"); }
~Base() { print("Base destroyed"); }
virtual void printData() = 0;
};
class Derived1 : public Base
{
protected:
int b;
public:
Derived1(int a, int b): b(b), Base(a) { print("Derived1 contructed"); }
~Derived1() { print("Derived1 destroyed"); }
};
class Derived2 : public Derived1
{
protected:
int c;
public:
Derived2(int a, int b, int c) : c(c), Derived1(a, b) { print("Derived2 contructed"); }
~Derived2() { print("Derived2 destroyed"); }
virtual void printData(){ //... }
};
Here, the constructor of Derived2 class created Derived1 via the initializer list and this in turn constructs Base "indirectly". This works like I expected.
However, in my complex Code, the Hunter class needs to explicitly call the WorldObject constructor. This looks like:
Hunter(sf::Texture &texture, float x, float y, sf::Font& font) :
WorldObject(texture,x, y, font),
Creature(texture, x, y, font)
{ //... }
Here, The Creature constructor just passes every argument to the WorldObject constructor. WorldObject only has this constructor:
WorldObject(sf::Texture& texture, float x, float y, sf::Font& font) : m_sprite(texture)
{ //... }
and the used Creature constructor looks like this:
Creature(sf::Texture &texture, float x, float y, sf::Font& font) :
WorldObject(texture, x, y, font),
NN(n_input_units, n_hidden_units, n_output_units)
{ //... }
Why do I need to initialize both WorldObject and Creature directly in my Programm, but in the toy example it works without the explicit Base constructor?
(( The pre-compiler is also complaining that there is no default constructor for WorldObject, and on compiling the above error appears))
I guess that in your complex code, Hunter directly inherits from WorldObject and not indirectly via Creature. If Creature inherits WorldObject, it will never be necessary for Hunter to pass any parameters to WorldObject.
I am trying to design a C++ Template class which will contain all the features of a Tree(i.e. appendChild, childCount). I want to then extend from this template class and design custom Tree class with existing features (read as Methods) as well as extra features.
So far I got this.
#include <iostream>
#include <list>
/* TREE TEMPLATE CLASS */
template <class T>
class TreeTemplate
{
public:
TreeTemplate();
void appendChild(T*);
int getChildCount();
protected:
std::list<T*> m_childList;
};
/* Constuctor */
template <class T>
TreeTemplate<T>::TreeTemplate(){}
template <class T>
void TreeTemplate<T>::appendChild(T* t)
{
m_childList.push_back(t);
}
template <class T>
int TreeTemplate<T>::getChildCount()
{
return m_childList.size();
}
/* CLASS INHERITTING TEMPLATE */
class TreeItem : public TreeTemplate<TreeItem>
{
public:
std::string getTestName();
TreeItem(std::string, std::string);
private:
std::string m_testID;
std::string m_testName;
};
TreeItem::TreeItem(std::string test_id, std::string test_name)
{
m_testID = test_id;
m_testName = test_name;
}
std::string TreeItem::getTestName()
{
return m_testName;
}
/* MAIN FUNCTION */
int main()
{
TreeItem *myTree = new TreeItem("9", "10");
TreeItem *child1 = new TreeItem("9.1", "10.1");
TreeItem *child2 = new TreeItem();
std::cout << myTree->getTestName() << std::endl;
myTree->appendChild(child1);
std::cout << myTree->getChildCount() << std::endl;
return 0;
}
Now, if I don't try to add some new Constructor in derived class (i.e. contructor overload), everything is good. But, if I am adding a new Constructor (as the code segment shows), I am failing to access the existing constructor (of Base Template class). I am getting following error in the line TreeItem *child2 = new TreeItem();
Am I doing something stupid here ? I can overload other methods, only failing at Constructor. How can I overload existing constructor of base template class?
There are two problems to address. The first is that when you define a constructor for a type, that type's default constructor is not implicitly generated. You can force it to be by using = default. Here is an example.
struct Foo {
Foo() = default; // Allows default construction
Foo(int value) : m_value(value) {}
int m_value;
};
The second problem is that a derived type does not inherit it's parent's class' constructors. Intuitively, in the following example, how can a constructor of type Base construct an instance of type Derived? Base is not aware of Derived's members.
class Base {
public:
Base(int x, int y) : m_x(x), m_y(y) {}
private:
int m_x;
int m_y;
};
class Derived : public Base {
public:
Derived(int x, int y, int z) : Base(x, y), m_z(z) {}
private:
int m_z;
};
void foo()
{
// If we use Base's constructor, what is m_z?
// Won't compile
Derived bar(1, 2);
}
Only the constructors of the type you are actually constructing are eligible, not it's base types' constructors. To simulate the behavior you will have to provide new constructors for the set of parameters you want to support.
class Derived : public Base {
public:
Derived(int x, int y, int z) : Base(x, y), m_z(z) {}
Derived(int x, int y) : Base(x, y), m_z(0) {}
private:
int m_z;
};
In certain cases you can work around this problem by supplying a variadic template constructor like the following example. This shouldn't be done in general, only when there is a particular need.
#include <utility>
class Base {
public:
Base(int x, int y) : m_x(x), m_y(y) {}
private:
int m_x;
int m_y;
};
class Derived : public Base {
public:
template<class ... Args>
Derived(Args&&... args) : Base(std::forward<Args>(args)...) {};
};
void foo()
{
Derived b(1, 2);
}
I am trying to create Circle and Rectangle from Class Shape. I want y to be assigned pi if I call Shape() constructor with a parameter (from circle class). Since Shape has a purely virtual function the compiler is showing error. How can I overcome this error. And why is default parameter running correctly then?
Also I tried this->Shape(0) from Circle class. Compiler is saying "Invalid use of this"
#include<iostream>
using namespace std;
class Shape
{public:
double x,y;
Shape()
{x=0;y=0;}
Shape(int p,int t=3.14159)
{x=p;y=t;}
virtual void display_area()=0;
virtual void get_data()=0;
};
class Circle: public Shape
{public:
Circle()
{Shape(0);} //ERROR HERE
void get_data()
{cout<<"\nRadius: ";cin>>x;}
void display_area()
{cout<<"\nArea: "<<y*x*x;}
};
base classes are always initialized before the constructor's block runs, so you do it in the constructor's member initialization list..
I also fixed another bug in your code.... You are doing some narrowing conversions, which wouldn't work as you want...
#include<iostream>
using namespace std;
class Shape
{
public:
double x,y;
Shape()
{
x=0;
y=0;
}
Shape(double p, double t=3.14159) //changed from Shape(int p, int t=3.14159)
{
x=p;
y=t;
}
virtual void display_area()=0;
virtual void get_data()=0;
};
class Circle: public Shape
{
public:
Circle() : Shape(0)
{ /*Shape(0); */ } //Not HERE
void get_data()
{
cout<<"\nRadius: ";
cin>>x;
}
void display_area()
{
cout<<"\nArea: "<<y*x*x;}
};
To call the base constructor you need to use the member initialization list.
Change:
Circle()
{
Shape(0);
} //ERROR HERE
To
Circle() : Shape(0)
{
}
I get next error, when compining code.
Error C2280 'Square::Square(void)': attempting to reference a deleted function objectfactory.h 11
I have next object factory, for objects:
template<class ID, class Base, class ... Args> class GenericObjectFactory {
private:
typedef Base* (*fInstantiator)(Args ...);
template<class Derived> static Base* instantiator(Args ... args) {
return new Derived(args ...);
}
std::map<ID, fInstantiator> classes;
public:
GenericObjectFactory() {}
template<class Derived> void add(ID id) {
classes[id] = &instantiator<Derived>;
}
fInstantiator get(ID id) {
return classes[id];
}
};
Base class for example:
class BaseFigure
{
private:
BaseFigure(const BaseFigure&);
int m_params_num;
public:
BaseFigure() : m_params_num(0) {};
virtual void draw(WDraw &drawer)=0;
virtual void boundingBox(WDraw &drawer) = 0;
virtual ~BaseFigure() {};
};
And derived class from BaseFigure:
class Square :
public BaseFigure
{
private:
Point2d points[2];
public:
std::string type();
void draw(WDraw &drawer);
void boundingBox(WDraw &drawer);
~Square();
};
Square realization below:
void Square::draw(WDraw &drawer) {
Point2d cournerSecond(points[0].x(), points[1].y()), cournerFour(points[1].x(), points[0].y());
drawer.drawSegment(points[0], cournerSecond);
drawer.drawSegment(cournerSecond, points[1]);
drawer.drawSegment(points[1], cournerFour);
drawer.drawSegment(cournerFour, points[0]);
}
void Square::boundingBox(WDraw &drawer) {
this->boundingBox(drawer);
}
Example of using:
GenericObjectFactory<std::string , BaseFigure> figureFactory;
figureFactory.add<Square>("sq");
BaseFigure *sq = figureFactory.get("sq")();
I can't understand, where is error?
P.S Added Point2D and WDraw. All methods of this classes have realization.
class Point2d
{
public:
Point2d(double xx, double yy);
virtual ~Point2d(void);
double x() const { return m_dX; }
double y() const { return m_dY; }
private:
double m_dX;
double m_dY;
};
class WDraw
{
public:
WDraw(void);
virtual ~WDraw(void);
virtual void drawSegment(const Point2d& p1, const Point2d& p2);
};
This line:
classes[id] = &instantiator<Derived>;
sets up your instantiator to use this instantiated function:
static BaseFigure* instantiator() {
return new Square();
}
But Square isn't default-constructible, because its member:
Point2d points[2];
isn't default-constructible, because it has a user-declared non-default constructor:
Point2d(double xx, double yy);
hence the error. The implicitly declared Point2d default constructor is declared as deleted, which makes the implicitly declared default constructor of Square declared as deleted as well.
To make this work, you'd have to either add a default constructor to Point2d or allow a way to pass in arguments through Square's constructor into points. Probably the latter makes the most sense.
Barry already answered with the root cause. For the records, here a solution using your very nice variable argument template for a generic constructor:
Modified example of use:
GenericObjectFactory<std::string, BaseFigure, Point2d, double> figureFactory; //<===== A square could be constructed with top left point + width
figureFactory.add<Square>("sq");
BaseFigure *sq = figureFactory.get("sq")(Point2d(1.0,2.0), 2.0); //<===== Instatiate with right arguments
The error message then clearly shows that the appropriate constructor isn't found. Let's add it:
Square(Point2d tl, double w)
{
points[0] = tl;
points[1] = Point2d(tl.x()+w, tl.y()+w);
}
The array can't unfortunately not be initialized in the mem-initializer, so Point2d needs also a default constructor. So add it, and it compiles fine !
I am trying to define an interface called "Algorithm" which has a pure virtual method insertData(InputData* input).
The implementation of the interface is called "Algorithm1" and i want to implement method "insertData" using as a parameter "SpecificData" which is a child of "InputData" class.
Is it possible without type casting?
Obviously with this code i get an error from the compiler that the virtual function "insertData" is pure within "Algorithm1".
class Algorithm{
public:
virtual ~Algorithm();
virtual void insertData(InputData* input) = 0;
};
class Algorithm1 : public Algorithm{
public:
Algorithm1();
virtual ~Algorithm1();
void insertData(SpecificData* input){
input.getID();
input.getAdditionalNumbers;
/*Process input information etc.*/ };
};
class InputData{
public:
void setID(int id){ this->id = id; }
int getID(){ return id;};
private:
int id;
};
class SpecifiData : public InputData{
public:
list<int> getAdditionalNumbers(){/*Return various Numbers*/};
private:
list<int> extraInfo;
};
void main(){
SpecificData* data = new SpecificData();
Algorithm* alg = new Algorithm1();
alg->insertData(data);
}
For insertData to be the same function (rather than "hiding" the original insertData, you need the two functions to have the same arguments (and same return type).
The whole idea of interfaces using virtual functions is that "they appear the same from the outside". You should be able to build a list of objects, and perform the same operation with the same input data for all of the objects in the list.
If you are breaking that principle, you are "doing it wrong".
No, it wouldn't make sense.
Think about the following scenario - you have a container (vector/set w/e) of Algorithm* type objects and a function that takes this container and a InputData* in as an input and then iterate over them and call insertData(in) on each of the objects in the container, this of course should work properly, but if one of the objects in your container is of type Algorithm1 what will happen then?
I think, this is a typical example of "Factory Method" in design pattern term.
class Algorithm
{
public:
virtual ~Algorithm();
virtual void insertData(InputData* input) = 0;
};
class InputData
{
public:
void setID(int id){ this->id = id; }
int getID(){ return id;};
virtual list<int> getAdditionalNumbers() = 0;
private:
int id;
};
class Algorithm1 : public Algorithm
{
public:
Algorithm1();
virtual ~Algorithm1();
void insertData(InputData* input){
input.getID();
input.getAdditionalNumbers;
/*Process input information etc.*/ };
};
class SpecifiData : public InputData
{
public:
// implementation
virtual list<int> getAdditionalNumbers(){/*Return various Numbers*/};
private:
list<int> extraInfo;
};
void main()
{
InputData* data = new SpecificData();
Algorithm* alg = new Algorithm1();
alg->insertData(data);
}