2012-03-15 246 views
0

想象我有這樣的類層次結構:在C++中存儲對象類型的好方法是什麼?

Base 
A : Base 
B : Base 
C : B 

我希望能夠從Base對象(I need string, not enum) retrive一個string型。我希望也能到對象類型比較A類型,例如:

Object *object = new A(); 
if (object->type() == A::typename()) 
{ 
    //hooray! 
} 

現在我刨一個靜態函數添加到每個班級:

static string typename() {return "Different name for each class";} 

,然後我將有重新實現Base功能virtual string type()每一個派生類:

A: virtual string type() {return typename();} //A::typename 
B: virtual string type() {return typename();} //B::typename 
... 

我覺得這樣的設計看起來醜陋。有更好的方法來實現我的目標嗎?

爲什麼我需要這個: 我正在開發一款遊戲。有一個瓷磚地圖。每個圖塊上都有一個對象數組。有些物體可以放置在其他物體上。所以我想檢查是否允許將對象放在特定的tile中。例如:如果瓷磚有對象類型「鍋」,那麼花可以放在那裏。

+1

你知道了'type_id'對象的? (http://www.cplusplus.com/reference/std/typeinfo/type_info/) – Constantinius 2012-03-15 12:50:15

+4

你究竟想達到什麼目的?如果您希望每個類的特定行爲都實現一個基本方法,該方法將被每個繼承類重寫並實現其特定的行爲。測試「實例」不是面向對象的。 – giorashc 2012-03-15 12:52:59

+1

如果您需要通過您訪問的指針或引用而知道超出您所知的對象類型的信息,則可能需要審查您的OOP設計。 – 2012-03-15 12:54:20

回答

3

你可以用dynamic_cast實現同樣的目的。無論如何,你的類是多態的。

注意這至少是一種代碼味道。您不需要在精心設計的設計中找到實際的課程類型。你試圖解決什麼潛在的問題?

此外,typename是C++中的關鍵字,您應該以不同的方式命名您的方法。

編輯:對於這方面的一個可能更好的解決方案將有一個對象對可堆疊的名單,並有虛擬方法:

class Object 
{ 
    virtual bool canStack(const std::string& baseObject) = 0; 
}; 

class Flower 
{ 
    virtual bool canStack(const std::string& baseObject) 
    { 
     if (baseObject == "pot") 
      return true; 
     return false; 
    } 
}; 

現在我明白你爲什麼會希望得到名稱。

+0

感謝您的回答。請參閱我的編輯 – Andrew 2012-03-15 12:58:58

+0

Luchian:我更喜歡將字符串常量實際存儲爲常量。另外,因爲遊戲中會有很多類型,我不想依賴於我輸入「pot」時不會輸入錯誤 – Andrew 2012-03-15 13:16:13

+0

@Andrew如果您有一個可接受組合的集合,它會輕鬆很多保持。 – 2012-03-15 13:17:09

0

我正在尋找一個舒適的方式來做這個好幾天。 這是我最終做到的。解決方案務實,編譯速度快,便於攜帶,並且無需RTTI即可運行。然而,它使用#define,C++人員試圖避免經常。 也許有人可以將該代碼轉換爲使用模板的代碼,我也會對此感興趣。

基本上,指向靜態方法的指針用於與「靜態布爾中的其他」對象返回的指針進行比較IsTypeOf(_TypeCheckBase & other)「,以提供類型檢查。 另外你可以得到對象的名字。

#define TYPE_CHECK_IMPL(T) \ 
    static bool IsTypeOf(_TypeCheckBase& other) { \ 
        return other.GetType() == (unsigned int)&IsTypeOf; } \ 
    virtual unsigned int GetType() { \ 
        return (unsigned int)&IsTypeOf; } \ 
    public: virtual const string& GetTypeName() { \ 
        static string typeName = #T; \ 
        return typeName; } 

#define TYPE_CHECK_DECL(T) \ 
    typedef T _TypeCheckBase;\ 
    TYPE_CHECK_IMPL(T) 


class root 
{ 
    public: 
     TYPE_CHECK_DECL(root) 
}; 

class A: public root 
{ 
    public: 
     TYPE_CHECK_IMPL(A) 
}; 

class AA: public A 
{ 
    public: 
     TYPE_CHECK_IMPL(AA) 
}; 

class B: public root 
{ 
    public: 
     TYPE_CHECK_IMPL(B) 
}; 

不,你可以做到以下幾點:

inline void prn(std::string txt, bool val) 
{ 
    cout << txt << ": " << (val ? "true":"false") << endl; 
} 

#define CMP(foo,bar) prn(#foo "\tis type of " #bar " TypeName:\"" + bar.GetTypeName() + "\"", foo::IsTypeOf(bar)); 

int main(void) 
{ 

    A a; AA aa; 
    B b; 

    cout << endl; 

    CMP(A,a); 
    CMP(AA,a); 
    CMP(B,a); 

    CMP(A,aa); 
    CMP(AA,(*((A*)&aa))); 
    CMP(B,aa); 

    CMP(A,b); 
    CMP(AA,b); 
    CMP(B,b); 
} 

您使用以下是主要的方法:

  • 布爾美孚:: IsTypeOf(欄)與富是一個類類型而bar是直接或間接從你的根類類型派生的對象。

  • 串bar.GetTypeName()

相關問題