I could not understand what was happening here, I thought it was very strange, and, understanding the reason, I thought that a joint answer would be valuable to someone.
So, given this simple code:
#include <iostream> using namespace std; class Shape { public: int* a; Shape(){ cout<<"Default Shape constructor"<<endl; a = new int(8); // default } Shape(int n){ a = new int(n); cout<<"Shape(n) constructor"<<endl; } // copy constructor Shape(const Shape& s){ cout<<"Shape copy constructor"<<endl; a = new int(*(sa)); } Shape& operator=(const Shape& s){ cout<<"Shape operator="<<endl; if (&s == (this)) return (*this); // this.clear(); a = new int(*(sa)); return (*this); } virtual void draw(){ cout<<"Print Shape the number is "<<*a<<endl; }; virtual ~Shape(){ delete a; cout<<"Shape distructor"<<endl; } }; class Circle : public Shape { public: int b; Circle() { cout<<"Default Circle constructor"<<endl; b=0; } virtual void draw() { cout<<"Printing Circle. The number is "<<b<<endl; } ~Circle(){ cout<<"Circle distructor"<<endl; } };
Why do the following two tests give two different answers:
static void test1(){ Shape shape = Circle() ; shape.draw(); } static void test2(){ Shape* shape = new Circle() ; shape->draw(); delete shape; }
Good, because now I recognize the virtual mechanism, I decided that both tests will lead to the same result (Circle print). Although this is what happens in test2, it is not so in test1.
To understand why, I wrote what actually happens in the background.
Test1: 1. The program will execute the line " Circle () ". 1.1 the default constructor of the Shape is called (because the Circle is derived from Shape). 1.2 the default constructor is called Circle.
- The program performs the action " Form = ". This actually calls the Shape copy constructor. * Here you should notice that the copy constructor does not copy _vptr, which is an invisible field in Circle. It only copies the value of a and returns (* this). This is the real reason he doesn't print Circle.
Here I have another question. When I started test1, I got this conclusion: The default Shape constructor The default loop constructor The copy constructor of the form Circle dialog Format Formatter: 8 Shape trim
If the signature of the copy constructor is Shape (const Shape & s), according to this output, there is a call to copy the constructor before creating the form in the form. How can this happen?
Test2: 1. A new instance of the Circle class is built on the heap. (The New Circle line is executed) 2. A pointer to this address in memory in the heap is returned and placed in the form of a pointer. The first four bytes of this address contain a pointer to the Circle virtual table. This is why test1 is different from test2.
It is important to understand that the difference between the test has nothing to do with the fact that test1 creates a circle on the stack, and test2 creates a circle on the heap. Well, actually it has something to do with it. But the real reason is that the copy constructor does not copy _vptr.