2014-01-22 33 views
-3

实施例为什么我复制对象时会丢弃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 
} 

教师V表指针[0]是零当用gcc编译。 此外,叔叔的vtable指针保持其原始值,而不是被覆盖。 我的问题:为什么这样呢? 是否有一个清洁的解决方法?我可以去uncle._vptr=ifather->_vptr,仍然是便携式?什么是ORDINARY例程复制对象?我应该甚至提交一个错误? 注意:它应该复制整个对象的平台无关,因为不管对象类型的标识如何完成,因为它应该始终在对象的数据块内!

文章

Why does my C++ object loses its VPTr

没有帮助我,必须有不同的原因。

+2

只需使用复制构造函数,即可停止黑客行为。请使用'std :: vector'和'new'来代替'malloc'。如果您要编写C代码,使用C++有什么意义? –

+1

什么是*((long long *)&uncle)= 0xDEAF;'应该这样做?你想达到什么目的? – interjay

+0

'*((long long *)&uncle)= 0xDEAF;'应该证明只有NOTHING被写入vptr位置 - 任何*垃圾*都会保留。编辑:这意味着复制例程不会在指针指向的数据块的开始处开始 - 非常意外! – Ohnemichel

回答

3

据我了解,基本的问题是这样的代码:

#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"? 
} 

应报告“基地”或“派生”。

总之,赋值不会改变对象的类型

因此,它报告“派生”。

+0

AAAAhh,这是一个伟大的答案!它通过语言的定义来解释原因!意思是:你可以复制内容,但除非你为它分配新的内存,否则你永远不能改变现有的对象。好。这是一个好点。它使实现更容易。但对我而言,这意味着我必须编写非常不整洁的代码,或者坚持自制面向对象的实现,以便能够操纵现有对象的类。非常感谢! Cheers - Ohnemichel – Ohnemichel

+0

这是为什么?因为您已使用某个默认提供程序赋值运算符将Base复制到Derived中? – paulm

+0

否 - 因为我无法将对象填充到预先分配的数组中。复制构造函数的使用不起作用。或者有没有办法与新的运算符一起使用复制构造函数?那么它会工作。 – Ohnemichel

相关问题