简体   繁体   English

虚拟继承(钻石)-为什么需要从派生程度最高的类上转换为基类

[英]Virtual inheritance (diamond) - Why do I need to upcast to Base class from the most Derived class

consider the following : 考虑以下 :

#include <iostream>
#include <string>
using namespace std;


class A {
public:
   A(const char* sName) //conversion constructor
           : _sName(sName) {cout<<"(1)"<<endl;} ;
   A(const A& s) {cout<<"(2)"<<endl;} //copy constructor
   virtual ~A() {cout<<"(3)"<<endl;} //destructor
    void f1() {cout<<"(4)"<<endl; f2();} //Notice two commands!
    virtual void f2() =0;
  private:
    string _sName;
  };



  class B1: virtual public A {
  public:
     B1(const char* sAName, const char* sSName)
             : _sName1(sAName), A(sSName) {cout<<"(5)"<<endl;}
     B1(const B1& b1) : A(b1) {cout<<"(6)"<<endl;}
     ~B1() {cout<<"(7)"<<endl;}
     virtual void f1() {cout<<"(8)"<<endl;}
     virtual void f2() {cout<<"(9)"<<endl; f3();}
     virtual void f3() {cout<<"(10)"<<endl;}
  private:
     string _sName1;
  };



  class B2: virtual public A {
  public:
     B2(const char* sAName, const char* sSName)
             : _sName2(sAName), A(sSName) {cout<<"(11)"<<endl;}
     B2(const B2& b2) : A(b2) {cout<<"(12)"<<endl;}
     ~B2() {cout<<"(13)"<<endl;}
     virtual void f3() {f1(); cout<<"(14)"<<endl;}
  private:
      string _sName2;
  };

  class C: public B1, public B2 {
  public:
         C () : A(" this is A ") , B1(" this is " , " B1 ") , B2 (" this is " , " B2 ") {}
         C (const C& c) :  A(c) , B1(c) , B2(c) {}
         ~C() {cout<<"(15)"<<endl;}
         virtual void f1() {A::f1(); cout<<"(16)"<<endl;}
         void f3 () {cout<<"(17)"<<endl;}
  };


  int main() {
      /* some code */
      return 0;
  }

As you can see , I added in class C the implementation of C's Ctor (constructor) . 如您所见,我在class C添加了C的Ctor(构造函数)的实现。 What is not clear to me is why do I need also the upcast from C to A , if B1 does that job for me in its Ctor ? 对我来说不清楚的是,如果B1在其Ctor中替我完成了工作,为什么我也需要从C到A的上行? Meaning , if I wrote C's Ctor as : 意思是,如果我将C的Ctor写成:

C () : A(" this is A ") , B1(" this is " , " B1 ") , B2 (" this is " , " B2 ") {}

why can't I write : 我为什么不能写:

C () : B1(" this is " , " B1 ") , B2 (" this is " , " B2 ") {}

thanks , Ronen 谢谢罗尼

In short, because it's what standard requires: you have to initialize virtual base in the ctor of the most derieved class. 简而言之,因为这是标准的要求:您必须在最受剥夺的类的ctor中初始化虚拟基数。

A more elaborated answer, it's because you have only one base sub-object for virtual bases and this sub-object might be initialized differently in different base classes. 一个更详尽的答案是,因为您只有一个用于虚拟基础的基础子对象,并且此子对象可能在不同的基础类中以不同的方式初始化。 Eg in your example 例如在您的示例中


C () : B1(" this is " , " B1 ") , B2 (" this is " , " B2 ") {}

What value do you expect to be passed to A ctor, " B1 " or " B2 "? 您希望将什么值传递给“ b1”或“ b2”?

Constructor of virtual base is called before nonvirtual ansestors ctor's. 虚拟基础的构造函数非虚拟anstors ctor 之前被称为。 In your example B1 ctor can not invoke the virtual base constructor for C as B1 ctor itself will be called later. 在您的示例中,B1 ctor无法调用C的虚拟基本构造函数,因为B1 ctor本身将在以后被调用。

Because 'B1' and 'B2' both use the same memory for 'A' that 'C' does. 因为“ B1”和“ B2”都使用与“ C”相同的“ A”存储空间。 If you didn't specify the construction of 'A' in 'C', which one of 'B1' or 'B2' should construct 'A'? 如果未在“ C”中指定“ A”的构造,那么“ B1”或“ B2”中的哪一个应构造“ A”?

Your terminology is slightly wrong here - this is not an upcast to 'A'. 您的术语在这里有点错误-这不是对'A'的偏up。

Because your class A does not have default constructor. 因为您的class A没有默认构造函数。

Compiler generates an default constructor for every class but once you explicitly overload the constructor it assumes you want to do something special and it does not generate the default constructor and when your code tries to invoke the default constructor it leads to an error. 编译器会为每个类生成一个默认的构造函数,但是一旦您显式重载该构造函数,它就会假定您要执行特殊的操作,并且不会生成默认的构造函数,并且当您的代码尝试调用默认的构造函数时,它将导致错误。

The following code statement: 以下代码语句:

C () : B1(" this is " , " B1 ") , B2 (" this is " , " B2 ") {}

leads to calling of the class A default constructor, which is not there at all, and hence results in an error. 导致调用类A的默认构造函数,该构造函数根本不存在,因此导致错误。 If you provide an default constructor for your class A that should compile fine without any errors too. 如果您为class A提供了默认构造函数,则该构造函数也可以正常编译而不会出现任何错误。

Here is a quick try: 这是一个快速尝试:

#include <iostream>

class A { public: A(int v) : m_v(v) { std::cout << "Initializing A with " << v << std::endl; } int m_v; };
class B1 : public virtual A { public: B1(int v) : A(v) {} };
class B2 : public virtual A { public: B2(int v) : A(v) {} };
class C : public B1, public B2 { public: C(int v1, int v2, int v3) : A(v1), B1(v2), B2(v3) {} };

int main()
{
    C c(1, 2, 3);

    std::cout << "c.m_v: " << c.m_v << std::endl;

    return EXIT_SUCCESS;
}

This example outputs: 此示例输出:

Initializing A with 1
c.m_v: 1

That is, it seems that the call to A::A() is required in the most derived class because since the inheritance is virtual , it won't get called by the constructors of B1 or B2 when instantiating C . 也就是说,似乎在最派生的类中需要对A::A()进行调用,因为由于继承是virtual ,因此在实例化CB1B2的构造函数不会调用它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 钻石 inheritance 中的虚拟类,在基础 class 和大多数派生 class 之间有多个类 - Virtual classes in diamond inheritance with multiple classes in between base class and most derived class 我是否需要在虚拟继承类的构造函数中为钻石继承问题初始化基类? - Do I need to initialize base class in virtual inheritance classes' constructors for diamond inheritanceproblem? 您是否需要从所有派生类调用虚拟基类构造函数? 即使他们不是最衍生的? - Do you need to call virtual base class constructor from all derived classes? Even if they're not the most derived? 金刚石 inheritance 带模板底座 class:底座<derived></derived> - Diamond inheritance with templated base class: Base<Derived> 为什么在创建大多数派生类的对象时,大多数基类(Virtual)的默认构造函数没有在私有虚拟继承中被调用? - Why default constructor of most base class (Virtual) is not getting called in private virtual inheritance while creating object of most derived class? 虚拟继承:Base Ctor没有调用Most Derived Class? - Virtual Inheritance : Base Ctor not calling in Most Derived Class? 如何调用所有基类的复制构造函数来复制C ++中钻石继承中的大多数派生类对象? - How to call copy constructor of all base classes for copying most derived class object in diamond inheritance in C++? 菱形多态继承:sizeof大多数派生类 - Diamond shaped polymorphic Inheritance: sizeof Most derived Class 虚拟 inheritance 中大多数派生 class 的大小 - Size of most derived class in virtual inheritance 为什么虚拟基类必须由最派生的类构造? - Why must virtual base classes be constructed by the most derived class?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM