C ++继承和polymprphism,非常有趣

时间:2017-09-29 01:40:24

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

好的伙计们, 这是我在尝试下面的代码时得到的一个非常奇怪的结果。 我尝试了两个编译器,来自visual studio的cl,以及onlinegdb.com上的gcc 结果是一样的,所以错误是可重复的,但结果本身并不明显,手工弄清楚。 检查代码中的注释,以了解我认为应该发生的事情。

    #include <iostream>
    using namespace std;

    class base
    {
     public:
          virtual void f() { cout << "in base::f()\n"; };
          virtual void g() { cout << "in base::g()\n"; };
          virtual ~base()  { cout << "base::~base()\n";};
    };

    class derived1 : public virtual base
    {
     public:
         derived1() { cout<<"dervied1 constructed\n"; };
         void f()   { cout << "in derived1::f()\n"  ; };
         ~derived1(){ cout << "derived1::~derived1()\n";};
    };

    class derived2 : public virtual base
    {
     public:
         derived2(base* b, derived1* d1)
         {
          cout<<"derived2 constructed\n";
          b->f();  
          d1->g();
         };

         void g() 
         {
          cout << "in dervied2::g()\n";
         };

         ~derived2()
         { 
          cout << "derived2::~derived2()\n";};
         };

    class C : public derived1, public derived2
    {
     public:
          C() : derived2 (this, this) {};

          void f() 
          { 
           cout << "in C::f()\n"; 
          };

          ~C() 
          { 
           cout << "C::~C()\n"; 
          };
    };

    int main()
    {
     derived1 d1;

     derived2 d2(&d1, &d1 ); // TAG 1

     base* c_as_b = new C;   //   TAG 2

     derived2* d2_as_c = new C; // same as TAG 2

     c_as_b->f();            // TAG 3
     d2_as_c->f();           // TAG 4

     delete d2_as_c;
     delete c_as_b;

     return 0;
    }

CODE OUTPUT:

dervied1 constructed <- result of: derived1 d1;                                                                                                  
derived2 constructed -|
in derived1::f()      | result of: derived2(&d1,&d1); // TAG 1
in base::g()         _|
dervied1 constructed -
derived2 constructed  |
in base::f()          | result of: base* b_as_c = new C; // TAG 2
in dervied2::g()     _|
dervied1 constructed -
derived2 constructed  |
in base::f()          | same as the above.
in dervied2::g()     _|
in C::f()
in C::f()
C::~C()
derived2::~derived2()
derived1::~derived1()
base::~base()
C::~C()
derived2::~derived2()
derived1::~derived1()
base::~base()
derived2::~derived2()
base::~base()
derived1::~derived1()
base::~base()

TAG 1: 具有正确的输出,遵循通过指向基类的指针访问派生类的规则。

标签2: 根据我的理解,在C类构造中,首先构造derived1和derived2,这意味着类C包含一个指向vtable的指针,其中derived1 :: f()覆盖base :: f(),而derived2 :: g()覆盖了base :: g(),所以在构建C类的这个时刻,C :: f()指向derived1 :: f()和C :: g()指向derived2 :: g()... ..但看起来只有一个指向最后一个类构造的vtable的指针,它是derived2,其中derived2 :: g()重写了base :: g(),并且没有覆盖base :: f() 。 [尝试颠倒C类的两个基类的顺序]

对我来说这是一个模糊的角落案例,但看起来所有编制者都同意结果!

有谁能解释这里发生了什么?

0 个答案:

没有答案