I couldn't figure out what is happening here, thought it is very strange, and after getting to understand the reason I thought sharing the answer would be valuable to somebody's time.
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(*(s.a));
}
Shape& operator=(const Shape& s){
cout<<"Shape operator="<<endl;
if (&s == (this))
return (*this);
// this.clear();
a = new int(*(s.a));
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 is the two following tests gives two different answers:
static void test1(){
Shape shape = Circle() ;
shape.draw();
}
static void test2(){
Shape* shape = new Circle() ;
shape->draw();
delete shape;
}
Well, because I'm getting to know the virtual mechanism just now, I figured that both test will produce the same result (printing Circle). While this is what happens in test2 it is not the case in test1.
To understand why, I wrote what really happens in the backround.
Test1: 1. The program perform the line " Circle() ". 1.1 a call to the default constructor of Shape is made (because Circle is derived from Shape). 1.2 a call to the default constructor of Circle is made.
Here I do have another question. When ran test1 I got this output: Default Shape constructor Default Circle constructor Shape copy constructor Circle distructor Shape distructor Print Shape the number is 8 Shape distructor
If the copy constructor signature is Shape(const Shape& s), according to this output, there is a call to copy constructor before actually creating shape as Shape. How can this happen?
Test2: 1. A new instance of class Circle is being build on the heap. (The line new Circle is performed) 2. A pointer to that address in memory on the heap is returned and placed in the pointer shape. In the first four bytes of this address lies the pointer to the virtual table of Circle. That is why test1 is different from test2.
It is important to understand that the the difference between the test has nothing to do with the fact that test1 builds a Circle on the stack and test2 builds 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 the _vptr.
It's called 'slicing' the class by copying (non-polymorphically) to the base type
See Thinking in C++ for backgrounder
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With