【问题标题】:Diamond Problem| Parmeterized constructor is not called of grandparent class钻石问题|不调用祖父类的参数化构造函数
【发布时间】:2018-09-17 12:51:39
【问题描述】:

有人可以解释一下下面的多重继承,为什么即使使用参数化构造函数构造车辆类,也不调用d类的参数化构造函数。

#include<iostream>

using namespace std;

class d{
    public:
    d()
    {
        cout<<"in default constructor of d"<<endl;
    }
    d(int x)
    {
        cout<<"in parametrized constructor of d"<<endl;
    }
    void a()
    {
        cout<<"a function of d";
    }
};
class Vehical:virtual public d
{
    public:
    Vehical(int x):d(x)
    {
     cout<<"In paramterized constructor of Vehical"  <<endl;
    }
    void a()
    {
        cout <<"a function of Vehical class"<<endl;
    }
    Vehical()
    {
     cout<<"default constructor of Vehical"<<endl;   
    }
};
class now: virtual  public d
{
public:
void a()
{
    cout <<"a function of now "<<endl;
}
    now()
{
  cout<<"Default constructor of now" <<endl; 
}
};
class car :public  Vehical, public now
{
    public:
    car();
    car(int y):Vehical(y)
    {

    };
     //using d::a;
       using Vehical::a;

};
int main()
{
 car ob(1);
  ob.a();
 return 0;
}

输出:

in default constructor of d
In paramterized constructor of Vehical
Default constructor of now

期望:它应该调用D的参数化构造函数而不是默认的,因为我们是通过传递参数来构造车辆,它确实调用了D类的参数化构造函数。

此外,如果我们删除一个类的虚拟,我们又会遇到钻石问题吗?为什么会这样?

场景 1): 如果我们从车辆类中删除虚拟,我们有以下输出

in default constructor of d
in parametrized constructor of d
In paramterized constructor of Vehical
Default constructor of now
a function of Vehical class

同样在上面的输出中,为什么首先调用默认构造函数,然后对 d 类进行参数化?另外在输出中,为什么首先调用 d 的构造函数,然后是车辆,现在是类构造函数。

期望:它应该首先调用 d 的参数化构造函数,然后调用车辆的参数化构造函数,然后调用 d 的默认构造函数,然后调用 now 的默认构造函数

场景 2) 现在我们从 now 类中删除 virtual 并且我们得到了输出,其中 d 的默认构造函数被调用而不是参数化?

in default constructor of d
In paramterized constructor of Vehical
in default constructor of d
Default constructor of now
a function of Vehical class

期望:它应该调用 D 的参数化构造函数,而不是第一行的默认构造函数。

【问题讨论】:

  • 您期望的输出是什么?为什么?
  • 对于1)它应该调用D的参数化构造函数而不是默认的,因为我们是通过传递参数来构造车辆,它确实调用了D类的参数化构造函数。
  • For 2)它应该首先调用 d 的参数化构造函数,然后调用 vehical 的参数化构造函数,然后调用 d 的默认构造函数,然后调用 now 的默认构造函数
  • for 3) 再次它应该调用参数化构造函数而不是 d 的默认构造函数
  • 请在问题中包含该内容。我个人觉得问题的最后一部分相当混乱。你基本上是同时问不同的问题。我可能会在“为什么会这样?”之后删除所有内容

标签: c++ virtual multiple-inheritance diamond-problem parameterized-constructor


【解决方案1】:

死亡恐惧钻石有两个问题:

1.基类的歧义——在引用这个“祖父”类时应该选择哪个基类的基类。

2.当显式调用基类构造函数时,祖父类的构造函数使用哪个。想象一下下面的例子:

class foo{
    public:
    foo() { }
    foo(int x) {  }
};
class bar : virtual public foo
{
    public:
    using foo::foo;
};
class baz: virtual  public foo
{
public:
    using foo::foo;
};
class clazz :public  bar, public baz
{
public:
    clazz(int i) : bar(i), baz(i+1){}
};

编译器应该选择foo 的哪个构造函数,因为只创建一个祖父?好吧,任何选择都意味着解决冲突的foo 构造函数调用之间的竞争(通过冲突我的意思是使用不同的参数)。 C++ 中的语言设计选择是 - 不要试图解决竞争,只是将初始化祖父类的责任推给程序员。这是有道理的,因为菱形继承是一个极端情况,可能需要特殊的初始化方式。

您必须在孙类构造函数中显式调用d 构造函数:

#include<iostream>

using namespace std;

class d{
    public:
    d()
    {
        cout<<"in default constructor of d"<<endl;
    }
    d(int x)
    {
        cout<<"in parametrized constructor of d"<<endl;
    }
    void a()
    {
        cout<<"a function of d";
    }
};
class Vehical:virtual public d
{
    public:
    Vehical(int x):d(x)
    {
     cout<<"In paramterized constructor of Vehical"  <<endl;
    }
    void a()
    {
        cout <<"a function of Vehical class"<<endl;
    }
    Vehical()
    {
     cout<<"default constructor of Vehical"<<endl;   
    }
};
class now: virtual  public d
{
public:
void a()
{
    cout <<"a function of now "<<endl;
}
    now()
{
  cout<<"Default constructor of now" <<endl; 
}
};
class car :public  Vehical, public now
{
    public:
    car();
    car(int y):Vehical(y), d(y)
    {

    };
     //using d::a;
       using Vehical::a;

};
int main()
{
 car ob(1);
  ob.a();
 return 0;
}

【讨论】:

  • 感谢您的回复。我知道解决方案,但为什么会发生这种情况?我还问了几个问题,如果你也回答这些问题会很有帮助。
  • @curositykiller 每个问题一个问题
  • @user463035818 它们都是相关的,这就是为什么:)
  • @curositykiller 希望它现在可以解释一些事情
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-31
  • 2021-07-17
  • 1970-01-01
  • 2018-02-28
  • 2014-06-15
  • 1970-01-01
相关资源
最近更新 更多