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

C++ 在C+;中存储对象类型的好方法是什么+;?,c++,inheritance,types,C++,Inheritance,Types,假设我有这样的类层次结构: Base A : Base B : Base C : B 我希望能够从Base对象检索字符串类型(我需要字符串,而不是枚举)。我还希望能够将对象类型与A类型进行比较,例如: Object *object = new A(); if (object->type() == A::typename()) { //hooray! } 现在,我计划为每个类添加一个静态函数: static string typename() {return "Different

假设我有这样的类层次结构:

Base
A : Base
B : Base
C : B
我希望能够从
Base
对象
检索
字符串
类型(我需要字符串,而不是枚举)
。我还希望能够将对象类型与
A
类型进行比较,例如:

Object *object = new A();
if (object->type() == A::typename())
{
   //hooray!
}
现在,我计划为每个类添加一个静态函数:

static string typename() {return "Different name for each class";}
然后我必须为每个派生类重新实现
Base
函数
虚拟字符串类型()

A: virtual string type() {return typename();} //A::typename
B: virtual string type() {return typename();} //B::typename
...
我觉得这样的设计很难看。有没有更好的方法来实现我的目标

我为什么需要这个:
我正在开发一个游戏。有一张平铺地图。每个磁贴上都有一组对象。某些对象可以放置在其他对象上。因此,我想检查是否允许将对象放置在特定的磁贴上。例如:如果瓷砖具有类型为“pot”的对象,则可以将花放在那里。

您可以使用
动态\u cast
实现同样的效果。你的类是多态的

注意这至少是一种代码气味。您不需要在经过深思熟虑的设计中找到实际类型的类。你想解决什么潜在的问题

也可以,<代码> >类型名称<代码>是C++中的关键字,应该对方法进行不同的命名。p> 编辑:一个可能更好的解决方案是有一个可以堆叠的对象对列表,并有虚拟方法:

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;
   }
};

现在我明白了为什么要使用get名称。

使用
动态\u cast
可以实现同样的效果。你的类是多态的

注意这至少是一种代码气味。您不需要在经过深思熟虑的设计中找到实际类型的类。你想解决什么潜在的问题

也可以,<代码> >类型名称<代码>是C++中的关键字,应该对方法进行不同的命名。p> 编辑:一个可能更好的解决方案是有一个可以堆叠的对象对列表,并有虚拟方法:

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;
   }
};

现在我明白你为什么想要这个名字了。

几天来我一直在寻找一种舒适的方法。 下面是我最后是怎么做到的。该解决方案实用、编译速度快、可移植,且无需RTTI即可工作。 但是,它使用的是一个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);
}
inline void prn(std::string txt,bool val)
{

好几天来,我一直在寻找一种舒适的方法来做这件事。 下面是我最终的解决方案。该解决方案实用、编译速度快、可移植且无需RTTI。 但是,它使用的是一个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);
}
inline void prn(std::string txt,bool val)
{

您是否知道
type_id
对象?()您到底想实现什么?如果您想要每个类的特定行为,请实现一个基方法,该基方法将被每个继承类覆盖,并实现其特定的behvior。测试“的实例”不是OOP的内容。如果您需要有关对象类型的信息,而不是通过访问对象的指针或引用所知道的信息,则可能需要检查OOP设计。@giorashc:请参阅我的编辑,查看访问者模式。您知道
type\u id
对象吗?()你到底想实现什么?如果你想为每个类实现一个特定的行为,实现一个基类方法,该基类方法将被每个继承类覆盖,并实现其特定的behvior这不是OOP的意义所在。如果您需要有关对象类型的信息,而不是通过访问对象的指针或引用所知道的信息,则可能需要检查OOP设计。@giorashc:请参阅我的编辑,查看访问者模式。Luchian:我更喜欢将字符串常量作为常量存储。另外因为游戏中会有很多类型,我不想依赖于我输入“pot”不会出错@Andrew如果你有一个可接受的组合集合,那么维护起来就会容易得多。Luchian:我更喜欢将字符串常量存储为常量。另外,因为游戏中会有很多类型,我不想依赖这些类型,我不会错误地键入“pot”@Andrew如果您有一组可接受的组合,那么维护起来就会容易得多。