2012-12-28 26 views
3

所以這可能是一個奇怪的問題,但我有一個相當好的理由要求。永久向下C++指針

我的問題的要點是,給定對一個類層次導出的兩個級別的示例:

主基類:

class Animal 
{ 
    virtual void Draw() = 0; 
}; 

派生類:

class Dog : public Animal 
{ 
    virtual void Draw() 
    { 
    // draw a generic dog icon or something... 
    } 
}; 

進一步來源:

class Corgi : public Dog 
{ 
    virtual void Draw() 
    { 
    // draw a corgi icon... 
    } 
}; 

現在,我希望能夠從Corgi課程中將「this」指針永久性地下注到指針Dog,然後將它作爲動物傳遞到其他地方。然後這個其他地方可以調用Draw函數並獲得Dog方法,而不是虛擬Corgi方法。我知道這很奇怪,但我又有一個想要這樣做的模糊理由。

我已經嘗試了所有不同的鑄造操作員,並沒有任何運氣,但也許有一個一致的方式拉這個關閉?在過去,我通過不正確地使用dynamic_cast而導致了自己的麻煩,這導致類似於指針的狀態。也許這次我可以利用這個優勢?

編輯: 也許上面的例子中並沒有說明清楚我想要實現的,所以我會用我的實際目標闡述。

我試圖實現一個簡化的註冊基類實現,鏈接到我已經使用了一段時間的腳本系統。腳本系統依靠基類IScriptContext來方便訪問實體代碼函數和成員變量訪問。內部基類註冊其成員函數地址和成員變量地址,這些地址稍後將通過查找表進行調度/訪問。我正在爲腳本系統添加對類派生層次結構的適當支持,並且我認爲能夠隔離這些接口的基類版本將有助於節省時間,並在需要時使整個過程更清潔。用腳本解釋器註冊可用的基類。還有其他方法可以實現這一點,例如爲每個可用基類的每個必需方法註冊類特定函數指針(例如,this->Dog::CallFunction,this->Dog::SetMember,this->Dog::GetMember)。但是,我想通過使用接口可以讓我更容易地修改某些東西如果我需要這條路。

我希望所有這些都有一定的意義。

謝謝!

+2

'我知道這是奇怪的,但同樣,我有一個模糊的正當理由想要做it.'這句話包含了矛盾。你想在這裏做什麼? –

+2

我認爲你的意思是「上傳」,而不是「下調」。 –

+1

如果你的'Corgi'對象需要表現得像'Dog's一樣,那麼它們應該包含代碼以使它們表現得那樣。也許是一個'isDog'標誌以及'Draw'中的一個測試,就像'if(isDog){Dog :: Draw();返回; }'。 –

回答

6

您有一個Corgi對象。您可以:

  1. 將其視爲Dog對象到處使用Dog::預選賽將所有來電(例如ptr->Dog::draw();)。這會讓你失去虛擬派遣,幾乎肯定不是你想要的問題。

  2. 實際上從您的Corgi構建一個新的Dog對象。只需要使用正常的static_cast來執行此操作,因爲您可以轉換任何其他類型或讓隱式轉換接管(例如Corgi c; Dog d(c);)。

這些是您可以選擇的選項。想要保留Corgi但自動假裝它是Dog既不合理也不合法,因此該語言未提供。

+0

我想我必須走這條路。它在路上會變得不太靈活,但它看起來像我唯一的選擇。謝謝! – worstoo

+1

@worstoo:我意識到你已經拋棄了這個選項,因爲無論出於何種原因(NIH?),這個選項都很受歡迎,但是我想重新提出一個建議,即退後一步,思考它是什麼正在努力完成。希望這會導致您對設計的重新考慮。 –

2

讓我開始說你的設計看起來有問題。

但是,您可以明確地說你要調用的函數在一個層次:

Corgi* corgi = new Corgi; 
corgi->Dog::draw(); 

這將調用draw方法從Dog,而不是從Corgi。 (我希望我能正確理解你在問什麼)。

2

託默勒格有already outlined兩個可用到您的主要選擇的:

  • 使用合格的來電,或

  • 構建Dog作爲CorgiDog副本。

除了這些,你可以

  • 用一個簡單的包裝

例如

class LooksLikeDog 
    : public Dog 
{ 
private: 
    Dog* realObject_; 

    LooksLikeDog(LooksLikeDog const&);     // No such. 
    LooksLikeDog& operator=(LooksLikeDog const&);   // No such. 

public: 
    LooksLikeDog(Dog& other) 
     : realObject_(&other) 
    {} 

    // Just for exposition: not implementing this does the same. 
    virtual void draw() override { Dog::draw(); } 

    // Example of other method that may need to be implemented: 
    virtual void bark() override { realObject_->bark(); } 
}; 

但是,最好的解決方案是最有可能對解決您的設計。 ;-)

+0

誰是你說話的神祕,奇妙的「Tomalak」角色,乾杯和歡呼聲。 - Alf? –

0

實現柯基繪製函數並調用你父母的實現:

virtual void Corgi::Draw() 
{ 
    Dog::draw(); 
}