{{notification.text}}

MirGames

02.11.09 18:57
0
:hi:
Вот есть такой код:
Код
#include <typeinfo>
#include <string>
#define CLASS_INFO(class_name,base_class) public: \
  virtual std::string ClassName(){return #class_name;}; \
  bool IsDerivedFrom(void *pObjFrom) \
  { \
  if(typeid(class_name) == typeid(*(class_name*)pObjFrom)) \
  return true; \
  return dynamic_cast<base_class*>(this)->IsDerivedFrom(pObjFrom); \
  }
#define CLASS_INFO_ROOT(class_name) public: \
  virtual std::string ClassName(){return #class_name;}; \
  bool IsDerivedFrom(void *pObjFrom) \
  { \
  if(typeid(class_name) == typeid(*(class_name*)pObjFrom)) \
  return true; \
  return false; \
  }

class O{CLASS_INFO_ROOT(O)};
class A: public O
{CLASS_INFO(A,O)};
class B: public A
{CLASS_INFO(B,A)};
class C: public B
{CLASS_INFO(C,B)};
class AnyChild: public B
{CLASS_INFO(AnyChild,B)};

void Test()
{
  A* a=new A; B* b=new B; C* c=new C;
  //
  AnyChild* px=new AnyChild;
  // вернёт xz
  bool FlagA = px->IsDerivedFrom(a); printf("FlagA = %s\n",FlagA?"True":"False");
  bool FlagB = px->IsDerivedFrom(b); printf("FlagB = %s\n",FlagB?"True":"False");
  bool FlagC = px->IsDerivedFrom(c); printf("FlagC = %s\n",FlagC?"True":"False");
  //
  printf("\n");
  printf("a->ClassName = %s\n",a->ClassName().c_str());
  printf("b->ClassName = %s\n",b->ClassName().c_str());
  printf("c->ClassName = %s\n",c->ClassName().c_str());
  printf("\n");
  printf("px->ClassName = %s\n",px->ClassName().c_str());
  printf("\n");
}

int main(){Test(); system("PAUSE"); return 0;};

Запускаем получаем вот это:
Код
FlagA = True
FlagB = True
FlagC = False

a->ClassName = A
b->ClassName = B
c->ClassName = C

px->ClassName = AnyChild

Заменяем строчку:
Код
AnyChild* px=new AnyChild;
на
Код
void* x=new AnyChild; O* px=(O*)(x); //поднялись снизу вверх
и мой мозг отказываться понимать результат:
Код
FlagA = False
FlagB = False
FlagC = False

a->ClassName = A
b->ClassName = B
c->ClassName = C

px->ClassName = AnyChild
Объясните почему ClassName работает правильно, а IsDerivedFrom нет?
ps: не хотел спрашивать, но сам так и не смог разобраться.
#1
Почётный лектор
02.11.09 19:50
0
Сдается мне, проблема в
Код
if (typeid(class_name) == typeid(*(class_name*)pObjFrom))


Попробуй вот что:
Код
bool IsDerivedFrom(void *pObjFrom)                                               \
{                                                                                                   \
    if (pObjFrom->ClassName() == ClassName())                               \
        return true;                                                                             \
    return static_cast<base_class*>(this)->IsDerivedFrom(pObjFrom); \
}

Ну и для рута аналогично

Для надежности, вместо
Код
virtual std::string ClassName(){return #class_name;}

лучше
Код
virtual std::string ClassName(){return typeid(class_name).name();}

А то могут быть одноименные классы в разных неймспейсах.
Отредактировано: 02.11.09 19:52
#2
03.11.09 03:23
0
Код
if (pObjFrom->ClassName() == ClassName())
Ыы. pObjFrom не умеет определять свой ClassName, он же void* и может быть NULL :).

Вот подсунул костыль :)
Код
#define CLASS_INFO(class_name,base_class) public: \
  virtual std::string ClassName(){return typeid(class_name).name();} \
  bool IsDerivedFrom(void *pObjFrom) \
  { \
  O* Temp=(O*)pObjFrom; \
  if (Temp->ClassName() == ClassName()) return true; \
  return static_cast<base_class*>(this)->IsDerivedFrom(pObjFrom); \
  }
#define CLASS_INFO_ROOT(class_name) public: \
  virtual std::string ClassName(){return typeid(class_name).name();} \
  bool IsDerivedFrom(void *pObjFrom) \
  { \
  O* Temp=(O*)pObjFrom; \
  if (Temp->ClassName() == ClassName()) return true; \
  return false; \
  }
Результат по прежнему такой:
Код
FlagA = False
FlagB = False
FlagC = False

a->ClassName = class A
b->ClassName = class B
c->ClassName = class C

px->ClassName = class AnyChild

Added: о_О, нет теперь даже очевидная вещь не работает AnyChild* px=new AnyChild;

пойду пробовать без макросов.
Отредактировано: 03.11.09 03:28
#3
03.11.09 05:07
0
Цитата(Universal @ Вчера, 15:50)
[snapback]99575[/snapback]
Сдается мне, проблема в
кстати, я это взял отсюда

Во сейчас макросы раскрыл и посмотрел.
если px определить как
Код
void* x=new AnyChild; O* px=(O*)(x);

То вот эта строчка:
Код
bool FlagA = px->IsDerivedFrom(a);
вызывается метод IsDerivedFrom отсюда:
Код
class O
{
public:
  virtual std::string ClassName(){return "O";};
  bool IsDerivedFrom(void *pObjFrom)
  {
    if(typeid(O) == typeid(*(O*)pObjFrom)) return true;
    return false;
  }
};
Вместо того чтобы вызываться отсюда:
Код
class AnyChild: public B
{
public:
  virtual std::string ClassName(){return "AnyChild";};
  bool IsDerivedFrom(void *pObjFrom)
  {
    if(typeid(C) == typeid(*(C*)pObjFrom)) return true;
    return dynamic_cast<B*>(this)->IsDerivedFrom(pObjFrom);
  }
};


И я снова не понимаю почему не работает наследование. Что в С++ надо написать вместо дельфийского override, что бы получить такой же эффект?

Added: Может эта строчка делает не то что я думаю:
Код
void* x=new AnyChild; O* px=(O*)(x);
Она ведь правда не копирует один объект с указателя в другой? да? да???...
Отредактировано: 03.11.09 05:23
#4
03.11.09 05:48
0
>ааа... хапец, йа дятло

Всё разобрался. Вот тру-код:
Код
#include <typeinfo>
#include <string>
#define CLASS_INFO(class_name,base_class) public: \
  virtual std::string ClassName(){return #class_name;}; \
  virtual bool IsDerivedFrom(void *pObjFrom) \
  { \
  if(typeid(class_name) == typeid(*(class_name*)pObjFrom)) \
  return true; \
  return base_class::IsDerivedFrom(pObjFrom); \
  }
#define CLASS_INFO_ROOT(class_name) public: \
  virtual std::string ClassName(){return #class_name;}; \
  virtual bool IsDerivedFrom(void *pObjFrom) \
  { \
  if(typeid(class_name) == typeid(*(class_name*)pObjFrom)) \
  return true; \
  return false; \
  }

class O{CLASS_INFO_ROOT(O)};
class A: public O
{CLASS_INFO(A,O)};
class B: public A
{CLASS_INFO(B,A)};
class C: public B
{CLASS_INFO(C,B)};
class AnyChild: public B
{CLASS_INFO(AnyChild,B)};

void Test()
{
  A* a=new A; B* b=new B; C* c=new C;
  //
  void* x=new AnyChild; O* px=(O*)(x); //поднялись снизу вверх
  // вернёт xz
  bool FlagA = px->IsDerivedFrom(a); printf("FlagA = %s\n",FlagA?"True":"False");
  bool FlagB = px->IsDerivedFrom(b); printf("FlagB = %s\n",FlagB?"True":"False");
  bool FlagC = px->IsDerivedFrom(c); printf("FlagC = %s\n",FlagC?"True":"False");
  //
  printf("\n");
  printf("a->ClassName = %s\n",a->ClassName().c_str());
  printf("b->ClassName = %s\n",b->ClassName().c_str());
  printf("c->ClassName = %s\n",c->ClassName().c_str());
  printf("\n");
  printf("px->ClassName = %s\n",px->ClassName().c_str());
  printf("\n");
}

int main(){Test(); system("PAUSE"); return 0;};
^_^

Universal
Спасибо!
#5
Почётный лектор
03.11.09 15:22
0
Не за что, я же ничем по сути не помог :)
#{{post.Index}}
{{post.Author.Login}}
{{post.CreatedDate | date:'dd.MM.yy HH:mm'}}
{{post.VotesRating}}
Отредактировано: {{post.UpdatedDate | date:'dd.MM.yy HH:mm'}}