2011-03-25 60 views
1

假設我有這樣的事情:如何避免C++爲特定類方法強制轉換?設計模式?

class Father { 
    public: 
     virtual int genericMethod (void) =0; 
    }; 

class Son1: public Father { 
    public: 
    int genericMethod() 
     { } 
    }; 

class Son2: public Father { 
    public: 
    int genericMethod() 
     { } 
    int specifClassMethod() 
     { } 
    }; 

在主我做了以下內容:

Father * test = new Son2(); 

test->specifClassMethod(); //Can't do this! It is specific of Class Son2 and is not a virtual method in class Father! 

這裏主要的問題是要知道更好的方式,通過父親的接口訪問Son2具體方法。我想知道是否有設計模式來解決這個問題或其他方式。我不想做演員陣容,也不想在演講中加入很多'if'。

問候,

愛德華

+1

你的例子是有點做作,是否有可能使它更具體? – 2011-03-25 12:23:20

+0

爲了比@Coda更加明確,您使用的實際設計是什麼,以便我們能夠指出它的缺陷?如果你的設計沒問題,那麼'dynamic_cast'是你的朋友。通常,使用'dynamic_cast'是嗅到代碼的標誌。 – 2011-03-25 12:27:04

+0

不要忘記添加虛擬析構函數到基類。否則,刪除「Father * test = ...;刪除測試;」不會調用正確的析構函數。 – 2011-03-25 12:36:21

回答

0

號調用哪隻在子類中存在的方法,你必須強制轉換爲CH ILD類。

雖然您可以創建一個映射函數名稱映射到函數,但從子類的構造函數中添加函數,然後使用類似test->callMethod("name");的東西,您必須使所有這些方法具有相同的簽名或使用可變參數傳遞不太好的論據。

0

可以static_cast<Son2*>(test)->specifClassCmethod();但只有工作,如果Father * test = new Son2();

0

如果你真的有特定Son2的東西,然後dynamic_cast<>是你應該用什麼。如果它可以作爲一個虛擬函數添加到基類的默認空行爲,那麼你可以在沒有演員的情況下解決你的問題(但這不是你想要做的,就像你在問題中說的那樣)

解決您的問題的一種設計模式是使用proxy object。那個對象會讓所有的方法容易被調用,並將它們委託給真實對象。代理模式的

優點:

  • 你集中精力區分後面一個地方的對象所需的邏輯
  • 你可以添加一些日誌記錄輕鬆地
  • 客戶端代碼保持簡單,Son類從額外的東西中清理出來
1

因爲「test」指向父對象而不是Son2對象。鑄造對象類型意味着「相信我,編譯器,這個變量實際上包含X」。它不會以某種方式神奇地將基礎對象轉換爲派生對象;它只會告訴編譯器你已經知道它沒有的東西。

如果您希望行爲因派生類而異,則將行爲移至虛擬方法 - 即,想要調用specificCLassMethod()的代碼屬於Father的虛擬方法。

+0

這裏有'dynamic_cast'。 – 2011-03-25 12:25:04

+0

不,那不是dynamic_cast所做的:它不能將一種類型轉換爲另一種類型。如果我有一個實際指向派生實例的指針,或者相反,dynamic_cast可以偏移指針以解釋vtbls或其他隱藏的對象模型問題。這隻有在對象的實際運行時類型如我所說的那樣時纔有效。 dynamic_cast不能神奇地將Son2的成員變量添加到父實例。 – 2011-03-25 12:31:56

0

首先,你不能爲類「父親」創建一個實例,因爲它是一個抽象類(具有虛擬INT genericMethod(無效)= 0;制純淨虛擬函數)。相反,一個實例可以被分配給它....

Son1* obj_son = new Son1(); 
Father* obj = obj_son; 
//now if you call generic method - son1 method will be called(Father method is over ridden) 
obj->genericMethod(); 
//similarly for son2 class 
Son2* obj_son2 = new Son2(); 
Father* obj2 = obj_son2; 
obj2->genericMethod(); 
obj2->specifClassCmethod(); 
2

可能的方法是有可選的方法的具體接口和虛擬的方法得到的基類此接口(可返回零):

class SpecificInterface { 
public: 
    virtual ~SpecificInterface() 
    { } 
    virtual int specifClassCmethod() = 0; 
    { } 
}; 

class Father { 
    public: 
    virtual int genericMethod (void) = 0; 
    virtual SpecificInterface* getSpecificInterface (void) =0; 
}; 

class Son1: public Father { 
    public: 
    int genericMethod() 
     { } 
    SpecificInterface* getSpecificInterface (void) 
     { return 0; } 
    }; 

class Son2: public Father, public SpecificInterface { 
    public: 
    int genericMethod() 
     { } 
    int specifClassCmethod() 
     { } 
    SpecificInterface* getSpecificInterface (void) 
     { return this; } 
    }; 

用法是以下:

Father * test = new Son1(); 
SpecificInterface * specificAPI = test->getSpecificInterface(); 
if(specificAPI) 
    specificAPI->specifClassCmethod(); 
相關問題