-2

I don't know the sequence of the code running,Please teach me When I create a point A *p=new C, what happen?I even can't understand this equation,why their class are different and it still can be compiled?

#include <iostream>
using namespace std;
class A
{
public:
  A( ){cout << "A Constructor" << endl;}
  virtual ~A( ){cout << "A Destructor" << endl;}
  virtual void f( ){cout << "A::f( )" << endl;}
  void g( ){ f( ); }
};


class B:public A
{
public:
  B( ){f();cout <<"B Constructor" << endl;}
  ~B( ){cout << "B Destructor" << endl;}
};

class C:public B
{
public:
  C( ){f( ); cout << "C Constructor" << endl;}
  ~C( ){cout << "C Destructor" << endl;}
  void f( ){cout << "C::f( )" << endl;}
};

int main()
{ 
  A *p=new C;
  p->g( );
  delete p;
}

output is

A Constructor
A::f( )
B Constructor
C::f( )
C Constructor
C::f( )
C Destructor
B Destructor
A Destructor
Abner
  • 47
  • 7

2 Answers2

3

A *p=new C, can be compiled because C is derived from (or inherits from) A. That's what

class C:public B

class B:public A

means. C is derived from B which is derived from A.

What that means is that every C object contains a B object inside it, and every B object contains an A object inside it. That's why you see the output that you see. When you construct a C object, it also constructs the B object inside it, and that also constructs the A object inside the B object.

It also means that it is possible to automatically convert a C* pointer to a B* pointer, and B* pointer to an A* pointer. That's why the code compiles.

This is basic information about class inheritance. I don't know where you got this code from but it should have explained this. Maybe you need to buy a good book on C++.

john
  • 85,011
  • 4
  • 57
  • 81
  • 1
    One other point of confusion that may be worth addressing is that the `B` constructor calls `A::f` because the `C` object is not (fully) constructed at that point, while the `C` constructor calls `C::f`, as does `A::g`. – dxiv Dec 26 '20 at 09:05
2
  1. A *p=new C; creates object of class C, creation of this object involves next steps.

  2. Constructor of class A is called, because if C is derived from some bases then first all bases constructors are called.

  3. In constructor of A string A Constructor is outputed, hence first string of output.

  4. Then constructor of B is called, because after calling constructors of all bases, next derived class constructor is called.

  5. Inside constructor of B function f() is called, because B has no f(), but there is f() in base A hence A::f() is called, hence second line of output.

  6. Inside constructor of B next output line B Constructor is printed.

  7. Then constructor of C is executed.

  8. Inside constructor C function f() is executed, as f() is contained inside C class hence it is called and prints fourth line C::f().

  9. Then inside C constructor is printed fifth line C Constructor.

  10. Then inside line A *p=new C; created pointer C* is casted and assigned (=) to A* because any derived class can cast its pointer to any base class.

  11. p->g() is called, it calls A::g(), which calls virtual f(). Any virtual function call calls most derived overriden variant of this function, hence A::f() actually calls C::f(), which prints sixth line C::f().

  12. Then pointer p is deleted inside line delete p;, hence class C is destructed. When object is destructed its destructors are called from most derived to most base class, so opposite to order of constructors.

  13. Because destructors are virtual hence when destructing A* actually destructor ~C() is called. Because virtual functions are called at the most derived class that overriden that function.

  14. When destructor ~C() is called, inside of it it calls three destructors in this order ~C(), ~B(), ~A(). So destructors are called in the order from most derived to most base class. I.e. opposite order of constructor.

  15. Destructors of C/B/A print last three lines C Destructor, B Destructor, A Destructor.

Arty
  • 14,883
  • 6
  • 36
  • 69
  • your 12th. you said when destruct A* ,~C is called ,but A destructor is printed..Why? – Abner Dec 26 '20 at 10:30
  • @Abner In 12) I told ~C() is called, but afterwards I say that destructors of all hierarchy is called, i.e. ~C() then ~B() then ~A(), also in 13) I say this more explicitly. I.e. when constructing C() three constructors are called in this order A(), B(), C(). But when destructing destructors are called in opposite order C(), B(),A() which is shown in last 3 output lines.So you have to remember if some object is constructed,not just its constructor is called, but all constructors of whole inheritance structure,i.e.C(),B(),A() three constructors are called,same for destructing but opposite order – Arty Dec 26 '20 at 10:37
  • I got it ,3Q!!! – Abner Dec 26 '20 at 10:43