首页 > 解决方案 > C++ 入门第 5 版。虚拟继承和ctor-init

问题描述

在 C++ 入门第 5 版上。第18章多重和虚拟继承,我有一个问题:

练习 18.30:在 Base 中定义一个默认构造函数、一个复制构造函数和一个具有 int 参数的构造函数。在每个派生类中定义相同的三个构造函数。每个构造函数都应该使用它的参数来初始化它的 Base 部分。

我试图以这种方式解决它,所以这是我的继承层次结构:

struct Class {
    Class(){cout << "Class()\n";}
    ~Class(){cout << "~Class()\n";}
};

struct Base : Class {
    Base(){cout << "Base()\n";}
    Base(int){cout << "Base(int)\n";}
    Base(Base const&){cout << "Base(Base const&)\n";}

    ~Base(){cout << "~Base()\n";}
};

struct D1 : virtual public Base {
    D1(){cout << "D1()\n";}
    D1(int x) : Base(x){
        cout << "D1(int)\n";
    }
    D1(D1 const& rhs) : Base(rhs){
        cout << "D1(D1 const&)\n";
    }

    ~D1(){cout << "~D1()\n";}
};

struct D2 : virtual public Base {
    D2(){cout << "D2()\n";}
    D2(int x) : Base(x){
        cout << "D2(int)\n";
    }
    D2(D2 const& rhs) : Base(rhs){
        cout << "D2(D2 const&)\n";
    }
    ~D2(){cout << "~D2()\n";}
};

struct MI : public D1, public D2 {
    MI(){cout << "MI()\n";}
    MI(int x) : Base(x), D1(x), D2(x){
        cout << "MI(int)\n";
    }
    MI(MI const& rhs) : Base(rhs), D1(rhs), D2(rhs){
        cout << "MI(MI const&)\n";
    }

    ~MI(){cout << "~MI()\n";}
};

struct Final : public MI, public Class {
    Final(){cout << "Final()\n";}
    Final(int x) : MI(x){
        cout << "Final(int)\n";
    }
    Final(Final const& rhs) : MI(rhs), Class(rhs){
        cout << "Final(Final const&)\n";
    }

    ~Final(){cout << "~Final()\n";}
};

现在,如果我编译程序,我会收到错误:

 error: ‘Class’ is an ambiguous base of ‘Final’

所以问题出在 classFinal的复制构造函数初始化列表中,所以我如何初始化复制构造函数中的子部分Class

所以帮助我解决这个问题。谢谢!

标签: c++constructorinitializationmultiple-inheritancevirtual-inheritance

解决方案


这是不可访问基类的情况。该类Final已经有一个继承链:

struct Final -> struct MI -> struct D1 -> struct Base -> struct Class

写东西 asclass Square: public Shape表示一种is-a关系,所以 Square is-a Shape。Final对于您的类链,它还Class通过许多中间父系谱系建立了相同的关系。写作public Class实际上是多余的struct Final : public MI, public Class。在现实世界的类比中,这类似于表明曾曾祖父是直系父亲,除非我们讨论的是幻想或反常的东西,否则这是不适用的。编译器在警告中声明它所提出的歧义,然后无法编译代码。这里有一个更细致入微的答案。对于您的具体问题,只需删除ClassfromFinal应该没问题用于编译。

PS 请考虑重命名Class为其他名称,因为这是 C++ 并且...class是一件大事。class Class会很不可读。


推荐阅读