Я не мог понять, что здесь происходит, подумал, что это очень странно, и после того, как я понял причину, я подумал, что поделиться ответом было бы полезно для кого-то.
Итак, учитывая этот простой код:
#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;
}
};
Почему два следующих теста дают два разных ответа:
static void test1(){
Shape shape = Circle() ;
shape.draw();
}
static void test2(){
Shape* shape = new Circle() ;
shape->draw();
delete shape;
}
Ну, поскольку я только сейчас узнаю виртуальный механизм, я решил, что оба теставыдаст тот же результат (круг печати).Хотя это то, что происходит в test2 , это не так в test1.
Чтобы понять почему, я написал, что действительно происходит в фоновом режиме.
Test1: 1. Программа выполняет строку « Circle () ».1.1 выполняется вызов конструктора Shape по умолчанию (поскольку Circle является производным от Shape).1.2 выполняется вызов конструктора Circle по умолчанию.
- Программа выполняет действие " Shape shape = ".Это фактически вызывает конструктор копирования Shape.* здесь вы должны заметить, что конструктор копирования не копирует _vptr, которое является невидимым полем в Circle.Он только копирует значение a и возвращает (* this).Это реальная причина, по которой он не печатает Circle.
Здесь у меня есть еще один вопрос.Когда я запустил test1, я получил такой вывод: Конструктор Shape по умолчанию Конструктор Circle по умолчанию Конструктор Copy Shape Конструктор Circle Distructor Shape Distructor Print Shape число 8Shape (const Shape & s) , в соответствии с этим выводом, существует вызов конструктора копирования перед фактическим созданием shape как Shape . Как это может произойти?
Test2: 1. В куче создается новый экземпляр класса Circle.(Строка new Circle выполняется) 2. Указатель на этот адрес в памяти в куче возвращается и помещается в указатель shape. В первых четырех байтах этого адреса лежитуказатель на виртуальную таблицу Circle.Вот почему test1 отличается от test2.
Важно понимать, что разница между тестами не имеет ничего общего с тем фактом, что test1 создает круг в стеке, а test2 создает круг в куче.,Ну, на самом деле это как-то связано с этим.Но настоящая причина в том, что конструктор копирования не копирует _vptr.