【问题标题】:Constructor for class must explicitly initialize the base class类的构造函数必须显式初始化基类
【发布时间】:2019-12-24 07:43:11
【问题描述】:

我有:

//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”

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

我不知道这是否与受保护的建筑商有关。或者如果是用于命名空间,虽然我不这么认为,因为代码编译后,直到我引入了 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不应该显式调用节点的Ctor吗?
  • 不需要,因为现在Node有default构造函数

标签: c++ inheritance constructor namespaces multiple-inheritance


【解决方案1】:

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

没有。

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

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

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

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

这种行为的理由可以在Section 12.6.2 Initializing bases and members/10.1的标准中找到

【讨论】:

  • 当我将默认构造函数设置为Node时,似乎没有调用Element的构造函数,我所有的节点都是UNDEFINED的类型
  • @quetzalfir,Element 的构造函数被调用,但 Tree::Node 的初始化仅从最派生类完成。您可以在Element 的构造函数主体中添加std::cout << "In Element()\n" 来验证这一点。
猜你喜欢
  • 2014-07-02
  • 2020-09-26
  • 2013-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多