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

4

我收到了:

//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',但该类没有默认构造函数

难道不是应该通过 Element 来初始化 Node 吗?为什么编译器要求我在那里显式初始化?
我不知道这是否与 builders 保护有任何关系。或者是否与命名空间有关,尽管我认为不是,因为代码已经编译通过,直到我引入了 SpecificElement 类。
我想在 SpecificElement 中调用 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
        }
    };
}

Element 应该显式调用 Node 的构造函数吗? - JVApen
不需要了,因为现在Node有一个“默认”构造函数。 - quetzalfir
1个回答

3

Node不是应该通过Element初始化吗?为什么编译器要求我显式初始化呢?

不是这样的。

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

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

SpecificElement(const std::string name) : Tree::Node(Node::ELEMENT) {
    nodename = name;
}

在这种情况下,当您构造一个SpecificElement实例时,Tree::Node子对象仅从SpecificElement的构造函数中初始化一次。 在Element的构造函数中的Tree::Node(Node::Element)部分会在运行时被忽略。

这种行为的正当理由可以在标准的第12.6.2节“初始化基类和成员/10.1”中找到


当我将默认构造函数设置为“Node”时,似乎未调用“Element”的构造函数,所有我的节点类型都为“UNDEFINED”。 - quetzalfir
@quetzalfir,Element 的构造函数被调用,但是 Tree::Node 的初始化仅在最派生的类中完成。您可以在 Element 构造函数的主体中添加 std::cout << "In Element()\n" 来验证这一点。 - R Sahu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接