ПримерПочему vptr отбрасывается при копировании объектов?
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <iomanip>
struct father
{
int variable;
father(){variable=0xEEEEEEEE;};
virtual void sing(){printf("trollolo,%x\n",variable);}
~father(){};
};
struct son:father
{
son(){variable=0xDDDDDDDD;};
virtual void sing(){printf("trillili,%x\n",variable);}
~son(){};
};
int main()
{
father * ifather=new(father);
son * ison=new(son);
father uncle;
father * iteachers;
*((long long*)&uncle)=0xDEAF;
iteachers=(father*)malloc(20*sizeof(father));
//ineffective assignments
iteachers[0]=*ifather;
uncle=*ifather;
ifather->sing();//called to prevent optimization
ison->sing();//only to prevent optimization
std::cout.setf(std::ios::hex);
std::cout<<"father:"<<*((long long*)ifather)<<","<<std::endl;
std::cout<<"teacher0:"<<*((long long*)&(iteachers[0]))<<","<<std::endl;
std::cout<<"uncle:"<<*((long long*)&uncle)<<","<<std::endl;
std::cout<<"(son:"<<*((long long*)ison)<<"),"<<std::endl;
// uncle.sing();//would crash
}
указатель виртуальных таблиц учителей [0] равно нуль при компиляции с GCC. Также указатель vtable дяди сохраняет свое первоначальное значение вместо того, чтобы быть перезаписанным. Мои вопросы: Почему это так? Есть ли CLEAN обходной путь? Могу ли я пойти с uncle._vptr=ifather->_vptr
и все еще быть портативным? Какова процедура ORDINARY для копирования объекта? Должен ли я даже регистрировать ошибку? Примечание: он должен скопировать всю платформу независимо от платформы, поскольку независимо от того, как выполняется идентификация типа объекта, поскольку она всегда должна находиться внутри блока данных объекта!
В статье
Why does my C++ object loses its VPTr
не помогли мне, что должны иметь разные причины.
Просто используйте конструктор копирования, прекратите взломать. И используйте 'std :: vector' и' new' вместо 'malloc'. Какой смысл использовать C++, если вы собираетесь писать C-код? –
Что такое '* ((long long *) & дядя) = 0xDEAF;' предполагается делать ?? Что вы пытаетесь достичь? – interjay
'* ((long long *) & дядя) = 0xDEAF;' должен просто продемонстрировать, что только ничего не записывается в местоположение vptr - любой * мусор *, который вы оставляете, сохраняется. Изменить: И это означает, что процедура копирования не начинается в начале блока данных, куда указатель направляется - очень неожиданно! – Ohnemichel