C++ 类的构造函数必须显式初始化基类

C++ 类的构造函数必须显式初始化基类,c++,inheritance,constructor,namespaces,multiple-inheritance,C++,Inheritance,Constructor,Namespaces,Multiple Inheritance,我有: //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 { pr

我有:

//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;
    }
};
SpecificElement
的构造函数中出现错误:

“SpecificElement”的构造函数必须显式初始化基 类“Tree::Node”,它没有默认构造函数

节点不应该通过元素初始化吗?为什么编译器要求我在那里显式初始化

我不知道这是否与建筑商受到保护有关。或者如果是名称空间,尽管我不这么认为,因为代码已经编译,直到我引入类
specific元素

我会在
specificeelement
中调用Node的构造函数,但我有更多的类继承自此,并且总的来说要求我显式初始化Node,而我不能通过设计来实现这一点

编辑: 感谢@r-sahu,我解决了它如下

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
        }
    };
}
节点
不应该通过
元素
初始化吗?为什么编译器要求我在那里显式初始化

没有

只有在创建
元素
的实例,而不是
元素
的子类时,才会发生这种情况。这与
virtual
继承有关

虚拟继承的类必须在派生最多的类的构造函数中正确初始化。因此,您必须使用:

SpecificElement(const std::string name) : Tree::Node(Node::ELEMENT) {
    nodename = name;
}
这样,当您构造
specifielement
的实例时,
Tree::Node
子对象仅从
specifielement
的构造中初始化一次。运行时将忽略
元素
的构造函数中的
树::节点(节点::元素)
部分


这种行为的理由可以在标准中找到,当我将默认构造函数设置为
节点
时,似乎没有调用
元素
的构造函数,我所有的节点类型都是
未定义的
@quetzalfir,调用了
元素
的构造函数,但
树::节点
的初始化仅从派生最丰富的类完成。您可以添加一个
std::cout元素,该元素不应该显式调用节点的Ctor吗?不需要,因为现在节点有一个
默认的
构造函数