2012-03-15 122 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()

相关问题