2011-08-17 21 views
0
class A 
{ 
public: 
    A(int i):pi(&i){} 
    int* func() 
    { 
    //dosomething 
    return pi; 
    } 
private: 
    int*pi; 
}; 

class B:public A 
{ 
    A*pa; 
public: 
    int* bar() 
    { 
     //dosomething 
     return pa->func(); 
    } 
}; 

int main() 
{ 
    A*pa=new B(); 
    int*pi=pa->bar(); 
    delete pa; 
    return 0; 
} 

如果我上面的類(我縮小了更好的視圖)是否可以進入嗎?我有點擔心,我選擇了一個錯誤的選擇。繼承和指針使用 - 正確使用的建議

+0

我在想'class A'虛擬析構函數在哪裏? – sharptooth

+0

這是不可能回答的。你想做什麼? –

+1

我建議找一本好的C++書,並從那裏開始。你顯然不理解*繼承*的概念! – Nim

回答

-2

您發佈的代碼不正確,有點混淆。

A*pa=new B(); 
    int*pi=pa->bar(); 

那不可能! A中沒有bar()函數,只是在B中。儘管創建了B對象,但是將它投射到A(實際上是你的缺失)。

林不知道你想要做什麼,但我認爲它會類似於一個接口。一個接口以這種方式工作: 您有一個抽象基類,它定義了一組(純)虛函數,並描述了一組固定的功能,如「loadData,saveData」等,但不包括如何實現此功能。您可以將數據實際上保存到一個XML文件,或者就像飛機二進制等(請注意:一個將使用流爲但對我來說我用這個作爲一個例子)

class YourInterface { 
public: 
    YourInterface(){ 
    } 

    virtual ~YourInterface(){ 
    } 

    virtual void saveData(Data data) = 0; //Pure virtual = Childs are forced to implement those functions to become non abstract 
    virtual Data loadData() = 0; 
}; 

//One implementation to load and save data to/from a xml file 
class XmlImplementation : public YourInterface { 
public: 
    XmlImplementation(){ 
    } 

    virtual ~XmlImplementation(){ 
    } 

    //Overriding functions: 
    void saveData(Data data){ 
     //Save data to a xml file here 
    } 

    Data loadData(){ 
     //Load data from a xml file here 
    } 
}; 

void main(){ 
    YourInterface* p; 
    p = (YourInterface*) new XmlImplementation(); 

    p->loadData(); //We just want to get our Data here, we dont care whether its from a xml or binary file etc. 
} 

注: 對不起,未完成的帖子我無意中碰到按鈕

+0

強制轉換爲基類指針是隱含的,所以他不會丟失強制轉換。另一方面,你使用C風格的演員陣容,你不應該在C++中做**,特別是當你試圖教某個人關於C++的時候。問題是'p =(YourInterface *)new int(42)'會靜靜地編譯,但是很不正確。如果投射到基礎上,總是讓它隱式地出現,如果投射到子類,使用'static_cast'或'dynamic_cast'作爲appropritate。 –

+0

對不起,然後,只記得我上次沒有鑄造問題。 – Paranaix

+0

如果您遇到問題,那是因爲您有其他問題。精心設計的C++代碼應該永遠不需要轉換,除了「功能風格」「轉換」(實際上是創建臨時實例的請求)。 –

0

您的代碼有幾個問題;這裏是其中的一些:

A(int i):pi(&i){} 

您正在接受通過值傳遞的參數的地址;當A的構造函數返回時,i將不再存在。

A*pa; 

B::pa從不初始化。

delete pa; 

您需要向A中添加一個虛擬析構函數才能正常工作。

+0

'刪除'是一個問題。你不能保證在B類的A類開始之前沒有偏移。 –

+0

@Let_Me_Be:這只是一個問題,因爲A沒有虛擬析構函數。這是因爲雖然A可能以B中的偏移量開始,但是編譯器將確保如果指針是A類型的,它指向實際A的實際開始,並且虛擬析構函數將會比正確地找到B的開始處。 –

+0

@ Jan是的,如果類是多態的,那麼刪除將正確釋放正確的指針。虛擬析構函數並不是完全需要的,你可以有一個私有的非虛擬析構函數來防止這個問題。 –

1

代碼有幾個問題。第一個是在這裏

A(int i):pi(&i){} 

這將成員pi指向參數i。然而i只要構造函數完成就會消失。現在你有一個指向任何地方的指針!

這裏

class B:public A 
{ 
    A*pa; 

類似的問題,即B類沒有任何用戶定義的構造的。這意味着pa將永遠不會指向任何地方。

第三個問題是在主

A*pa=new B(); 
// ... 
delete pa; 

,其中通過指針刪除對象基類,如果基類有虛析構函數才起作用。

如果您嘗試編譯代碼,您會發現構造函數的一些其他問題。