Reputation: 568
I've got:
//all classes are in different files
namespace Tree {
class Node {
NodeType type;
protected:
std::string nodename;
Node(Node::NodeType _type) : type(_type) {}
};
}
class Parent : public virtual Tree::Node {
protected:
Parent() : Node(Node::UNDEFINED) {}
};
class Child: public virtual Tree::Node {
protected:
Child() : Node(Node::UNDEFINED) {}
};
namespace Tree {
class Element :
public Parent,
public Child,
public virtual Node {
protected:
Element() : Node(Node::ELEMENT) {}
};
}
class SpecificElement: public Tree::Element {
public:
SpecificElement(const std::string name) {
nodename = name;
}
};
In the constructor of SpecificElement
appears the error:
Constructor for 'SpecificElement' must explicitly initialize the base class 'Tree::Node' which does not have a default contructor
Isn't Node supposed to be initialized through Element?, why the compiler ask me for explicitly initialize there?
I don't know if this has anything to do with the builders being protected. Or if it is for the namespaces, although, I don't think so, since the code compiled, until I introduced the class SpecificElement
.
I would call the constructor of Node in SpecificElement
, but I have many more classes that inherit from this, and in all asks me to initialize explicitly Node, and I can not do that by design.
EDIT: thanks to @r-sahu, I solved it as follow
namespace Tree {
class Node {
protected:
std::string nodename;
NodeType type; //changed to protected
Node(Node::NodeType _type) : type(_type) {}
Node() : Node(UNDEFINED) {} //default constructor
};
}
namespace Tree {
class Element :
public Parent,
public Child,
public virtual Node {
protected:
Element() { //change the init constructor list
type = Node::ELEMENT; //change type inside constructor
}
};
}
Upvotes: 4
Views: 6242
Reputation: 206567
Isn't
Node
supposed to be initialized throughElement
?, why the compiler ask me for explicitly initialize there?
No.
That happens only when you create an instance of Element
, not a sub-class of Element
. This has to do with virtual
inheritance.
Classes that are virtual
ly inherited must be initialized correctly in the constructor of the most derived class. Hence, you must use:
SpecificElement(const std::string name) : Tree::Node(Node::ELEMENT) {
nodename = name;
}
With that in place, when you construct an instance of SpecificElement
, the Tree::Node
sub-object is initialized only once, from the constructo of SpecificElement
. The Tree::Node(Node::Element)
part in the constructor of Element
is ignored at runtime.
The justification for this behavior can be found in the standard in Section 12.6.2 Initializing bases and members/10.1
Upvotes: 3