пример
#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
}
Указатель vtable учителя [0] равен нулю при компиляции с помощью gcc.
Кроме того, указатель vtable объекта uncle сохраняет свое первоначальное значение, а не перезаписывается.
Мои вопросы: почему так?
Есть ли ЧИСТЫЙ обходной путь? Могу ли я пойти с uncle._vptr=ifather->_vptr
и все же быть портативным? Что такое ОБЫЧНАЯ процедура для копирования объекта? Должен ли я даже сообщить об ошибке?
Примечание: он должен копировать весь объект, независимый от платформы, потому что независимо от того, как выполняется идентификация типа объекта, так как он всегда должен быть внутри блока данных объекта!
Статья
Почему мой объект C ++ теряет свой VPTr
не помогло мне, это должно быть по другой причине.
Насколько я понимаю, в основном вопрос заключается в следующем:
#include <iostream>
using namespace std;
struct Base
{
virtual void sing() { cout << "Base!" << endl; }
virtual ~Base() {}
};
struct Derived: Base
{
void sing() override { cout << "Derived!" << endl; }
};
auto main()
-> int
{
Base* p = new Derived();
*p = Base();
p->sing(); // Reporting "Base" or "Derived"?
}
должен сообщить «База» или «Производные».
Короче, назначение не меняет тип объекта.
Следовательно, сообщает «Производные».
Других решений пока нет …