在C ++中存储对象类型的好方法是什么?

时间:2012-03-15 12:47:55

标签: c++ inheritance types

想象一下,我有这样的类层次结构:

Base
A : Base
B : Base
C : B

我希望能够从string对象Base中检索(I need string, not enum)类型。我还希望能够将对象类型与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具有类型" pot"然后花可以放在那里。

2 个答案:

答案 0 :(得分: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;
   }
};

现在我明白为什么你想得到这个名字。

答案 1 :(得分:0)

我正在寻找一种舒适的方式来做这几天。 这是我最终做到的。该解决方案实用,编译速度快,便于携带,无需RTTI 。 然而,它使用#define,C ++人员经常试图避免。 也许有人可以将代码转换为使用模板的代码,我也会对此感兴趣。

基本上,指向静态方法的指针用于与“static bool IsTypeOf(_TypeCheckBase& other)”中的“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);
}

您在这里使用的主要方法是:

  • bool Foo :: IsTypeOf(bar),其中Foo是类类型,bar是对象,直接或间接从您的根类类型派生。

  • string bar.GetTypeName()