Что такое хороший способ хранить тип объекта в C ++? - PullRequest
0 голосов
/ 15 марта 2012

Представьте, что у меня есть такая иерархия классов:

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
...

Я думаю, такой дизайн выглядит безобразно. Есть ли лучший способ достичь моей цели?

Зачем мне это нужно: Я разрабатываю игру. Есть карта тайлов. Каждая плитка имеет массив объектов. Некоторые объекты могут быть размещены поверх других. Поэтому я хочу проверить, можно ли поместить объект на конкретную плитку. Например: если у плитки есть объект типа «горшок», тогда цветок можно положить туда.

Ответы [ 2 ]

3 голосов
/ 15 марта 2012

Вы можете достичь того же самого с 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 голосов
/ 15 марта 2012

Я искал удобный способ сделать это в течение нескольких дней. Вот как я это сделал наконец. Решение прагматично, быстро компилируется, переносимо и работает без RTTI . Однако он использует #define, которого C ++ часто стараются избегать. Может быть, кто-то может превратить этот код в тот, который использует шаблоны, которые мне также были бы интересны.

По сути, указатель на статический метод используется для сравнения с указателем, возвращаемым «другим» объектом в «static bool 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);
}

Основные методы, которые вы здесь используете:

  • bool Foo :: IsTypeOf (bar), где Foo является типом класса, а bar является объектом, производным прямо или косвенно от типа корневого класса.

  • string bar.GetTypeName ()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...