2014-01-12 37 views
0

首先:顯式調用基礎拷貝構造函數=> RTTI信息丟失。錯誤?

我問這個問題只是出於好奇,瞭解什麼是真正發生。我不使用這樣的生產代碼,所以我不想想看到答案,提出了另一種解決方案。

有了這個代碼:

class Base{ 
public: 
    virtual void copy(){} 
}; 

class Derived: public Base{ 
public: 
    void copy(){ 
     Base a1; 
     this->Base::Base(a1);//explicit call to base copy constructor 
    } 
}; 

我知道,某些情況下這是不好的顯式調用拷貝構造函數(當類是動態分配的成員,因爲該內存區域的引用將丟失它不會被釋放)。

對於下面的示例,我沒有看到調用基本複製構造函數的任何直接問題。乍一看,我認爲當調用copy()方法時,必須重新初始化基本子對象。

int main(){ 
    Base** _a = new Base*; 
    _a[0] = new Derived(10); 
    Derived* b = dynamic_cast<Derived*>(_a[0]); 
    assert(b);//<===true 
    _a[0]->copy(); 
    //t is still available and can be accessed through b 
    std::cout<<b->t;//correct: 10 
    b = (Derived*)_a[0]; 
    std::cout<<b->t;//correct: 10 
    b = dynamic_cast<Derived*>(_a[0]); 
    assert(b);//<===false  
} 

但是第二個斷言失敗。有人可以解釋這種行爲嗎?這是爲什麼發生?調用基礎拷貝構造函數時typeid是否丟失?

我編譯的代碼與Visual Studio 2012

+2

此代碼甚至不應該編譯... –

+0

@KerrekSB我沒有exect編譯要麼但我想一些東西,我意識到它編譯,我想知道發生了什麼。 –

+0

它編譯是因爲它與指向成員函數的指針相同。有A :: * t你可以打電話(this - > * t)() –

回答

3

構造函數之前類成員初始化vptr的指針設置爲類的虛函數表。手動調用父類的構造函數,使派生類vptr指向父類的vtable。

+0

這似乎是可行的。 –

+0

有趣的是,我檢查了__vfptr實際上已經改變了。 –

1

那麼,當您撥打Base::Base(const Base&)時,您正在爲分配給您的Derived類型對象的內存中創建一個Base類型的新對象。之後,所有的虛擬功能,例如,將指向他們的Base::實現。

如果你想重新初始化你的對象,你必須調用派生類型的構造函數Derived::Derived(const Derived&),你不能只重新初始化它的一部分。

旁白:
可以通過先破壞對象做出正確reinitializetion:

this->~Derived(); //cleanly destruct the object 
this->Derived::Derived(...); //rebuilt the object in place