Виртуальная таблица и нарезка объектов - PullRequest
0 голосов
/ 07 марта 2019

При нарезке объектов, когда объект производного класса копируется в объект базового класса, _vptr класса Derived также копируется в _vptr базового класса, как и другие члены класса Base?. Если нет, то почему?

class Base{  
public :
virtual void Display(){cout<<"In Base"<<endl;}
 };
class Derived:public Base{
public:
void Display(){cout<<"In Derived"<<endl;}

};
int main()
{
Derived objD;
Base objB;
objB = objD;
objB.Display();
}

Я наблюдал следующий результат для приведенного выше фрагмента.

Output
In Base

1 Ответ

0 голосов
/ 08 марта 2019

Все известные реализации используют vptr, но детали сильно различаются. Vptr - это способ для реализаций представлять тип объекта полиморфного класса (класс с виртуальными функциями), а иногда и классов с виртуальными базовыми классами (очень зависит от реализации).

Обратите внимание, что во многих случаях классы с более чем простым наследованием (одиночное не виртуальное наследование) имеют более одного vptr.

Значение vptr является функцией типа самого производного объекта, созданного.

Тип объекта не может быть изменен пользователем в течение его жизни; во время строительства тип объекта меняется в процессе его строительства; во время разрушения он меняется обратно. (Недопустимо ссылаться на объект во время строительства или разрушения с помощью имени или другого выражения, тип которого не соответствует объекту.)

Вы можете повторно использовать пространство существующего объекта для создания объекта другого типа, но это не тот же объект:

struct X {
  A a;
  B b;
  // requires: construction doesn't throw
};

void replace (X &x) {
  x.~X(); 
  B &b = *new (&x) B; // hope no exception here
  b.f(); // use as a normal B object
  x.f(); // undefined: cannot use x as a real object
  X *p = &x; // legal: x isn't used as an object, only as an address
  b.~B(); // clean up ressources if needed
  new (&x) X; // valid: &x refers to storage, as if a void*
  // x refers to a valid X object 
}

Такое повторное использование объекта не меняет тип любого существующего объекта: replace(x) не просто воздействует на x (оно уничтожает и восстанавливает один), оно действует на место хранения x , После вызова replace(x) имя x может использоваться для ссылки на вновь созданный объект X, который фактически взял идентификатор ранее существующего объекта X.

Никакой операции над объектом (которая поддерживает объект в живых) даже не разрешается изменять его тип в C ++. У vptr нет возможности изменить созданный объект.

Изменение типа объявленного объекта разрушило бы систему типов C ++ и инварианты объявленных объектов. Компилятор не будет знать, какой класс уничтожать, какие виртуальные функции вызывать, где находятся базовые классы и т. Д. Это полностью изменит способ работы C ++. Трудно даже представить семантику, связанную с изменением типа существующего объекта.

...