typeid.name() для наследуемого класса
От: V.I.P. Россия  
Дата: 27.10.05 16:21
Оценка:
Здравствуйте, подскачите пожалуйста
как узнать в базовом классе, имя класса наледуемого от него, т.е.


class A{
  public:
    A(){
        using namespace std;
        std::cout << typeid(*this).name() << "\n";
    }
};
class B:public A{
};

int _tmain(int argc, _TCHAR* argv[])
{
    A object1;
    B object2;
    getchar();
    return 0;
}

выводит class A
        class A

а хотелось бы class A
class В
что нужно дописать в конструкторе базового класса , что бы определялось имя наследуемого кдасса???
Re: typeid.name() для наследуемого класса
От: Brupus  
Дата: 27.10.05 16:41
Оценка:
Здравствуйте, V.I.P., Вы писали:

VIP>что нужно дописать в конструкторе базового класса , что бы определялось имя наследуемого кдасса???


Тут скорее всего ничего не поможет.
Ну, во первых, базовый класс ничего, кроме собственного интерфейса, о производных знать не может.
Во вторых, при создании объекта класса A в рамках создания объекта класса B последнего просто еще не существует.
А если производных классов больше одного?

А зачем вообще это надо? Ведь при создании объекта обычными средствами тип все равно заранее известен.
Re: typeid.name() для наследуемого класса
От: 0xDEADBEEF Ниоткуда  
Дата: 27.10.05 16:53
Оценка:
Здравствуйте, V.I.P., Вы писали:

VIP>что нужно дописать в конструкторе базового класса ,

Ничего. Так работать заведомо не будет.
До тех пор, пока все конструкторы не отработали, класс считается несконструированным и не знает о своих потомках.
И,следовательно, в typeid() который ты написал, всегда будет возвращать "A".

VIP>что бы определялось имя наследуемого кдасса???

Заведи хотя бы одну виртуальную функцию.

Пример
struct A
{
  virtual ~A()
     {} //чтобы магия работала

  void print()//а здесь виртуальности не надо совсем.
  {
     std::cout << typeid(*this).name() << "\n";
  }
};

struct B: public A
{
};

int main()
{
   A a; a.print();
   B b; b.print();
}
__________
16.There is no cause so right that one cannot find a fool following it.
Re[2]: typeid.name() для наследуемого класса
От: V.I.P. Россия  
Дата: 27.10.05 17:01
Оценка:
Здравствуйте, 0xDEADBEEF, Вы писали:

DEA>Здравствуйте, V.I.P., Вы писали:


VIP>>что нужно дописать в конструкторе базового класса ,

DEA>Ничего. Так работать заведомо не будет.
DEA>До тех пор, пока все конструкторы не отработали, класс считается несконструированным и не знает о своих потомках.
DEA>И,следовательно, в typeid() который ты написал, всегда будет возвращать "A".

VIP>>что бы определялось имя наследуемого кдасса???

DEA>Заведи хотя бы одну виртуальную функцию.

Задача состоит в логировании событий, что бы определить имена наследуемых (созданных) классов, а в бызовом классе
написать так чтобы при наследовании в лог писалось имя наследуемого класса
т.е. не вызавать b.print();
а просто написать B b; и автоматически в лог запишется имя наследуемого класса
Re[3]: typeid.name() для наследуемого класса
От: 0xDEADBEEF Ниоткуда  
Дата: 27.10.05 17:14
Оценка: +1
Здравствуйте, V.I.P., Вы писали:

VIP>Задача состоит в логировании событий, что бы определить имена наследуемых (созданных) классов,

VIP>а в бызовом классе написать так чтобы при наследовании в лог писалось имя наследуемого класса
Воспользуйся фабрикой классов, но тогда классы придется создавать на фристоре.
Например, так:

template<class T> 
std::auto_ptr<T> TheFactory()
{
   T *t = new T;
   t.print();// логаем
   return std::auto_ptr<T>(t)
}

//и, соответвсвенно
int main()
{
   std::auto_ptr<A> a( TheFactory<A>() );
   std::auto_ptr<B> b( TheFactory<B>() );
}


VIP>и автоматически в лог запишется имя наследуемого класса

typeid.name() возвращает не имя, а строку, уникальную для каждого класса. Это две большие разницы.
Например: в Visual C для "A" выведется "A", а вот GCC на юнихе выдаст тебе (и выдает) что-то совершенно неудобочитаемое типа "1A"
__________
16.There is no cause so right that one cannot find a fool following it.
Re[4]: typeid.name() для наследуемого класса
От: V.I.P. Россия  
Дата: 27.10.05 17:25
Оценка:
Здравствуйте, 0xDEADBEEF, Вы писали:


DEA>
DEA>template<class T> 
DEA>std::auto_ptr<T> TheFactory()
DEA>{
DEA>   T *t = new T;
DEA>   t.print();// логаем
DEA>   return std::auto_ptr<T>(t)
DEA>}

DEA>//и, соответвсвенно
DEA>int main()
DEA>{
DEA>   std::auto_ptr<A> a( TheFactory<A>() );
DEA>   std::auto_ptr<B> b( TheFactory<B>() );
DEA>}
DEA>


Это все хорошо, но проблема в том, что конечные пользователи библеотекой протоколирования
если захотят запротоколировать создание объектов, то каждый раз необходимо писать
std::auto_ptr<A> a( TheFactory<A>() ); и так для каждого объекта
а хотелось бы что то вроде того

    A(){
       NEW_OBJECT();
       //
    }

где NEW_OBJECT(); макрос раскывающийся в Log.New_Object(){//заносим в лог "Создан Обект его имя ..."}
Re[5]: typeid.name() для наследуемого класса
От: 0xDEADBEEF Ниоткуда  
Дата: 27.10.05 17:50
Оценка: :)
Здравствуйте, V.I.P., Вы писали:

VIP>Это все хорошо, но проблема в том, что конечные пользователи библеотекой протоколирования

Я уже говорил: в конструкторах typeid(*this) НЕ РАБОТАЕТ. Виртуальные функции тоже НЕ РАБОТАЮТ.
Таковы правила языка. То есть, твой подход НЕВЕРЕН. Ищи или другой подход или другой язык.

VIP>если захотят запротоколировать создание объектов, то каждый раз необходимо писать

VIP>std::auto_ptr<A> a( TheFactory<A>() ); и так для каждого объекта
Этe запись можно достаточно сильно сократить, но общая идея остается той же.

VIP>а хотелось бы что то вроде того

а мне хотелось бы миллиард в швейцарском банке, большой пистолет, а также лицензию на отстрел нескольких огранизмов...
__________
16.There is no cause so right that one cannot find a fool following it.
Re[6]: typeid.name() для наследуемого класса
От: V.I.P. Россия  
Дата: 27.10.05 17:56
Оценка:
Здравствуйте, 0xDEADBEEF,

Я конечно благадорен тебе за помощь, но че орем то??
я же знаю, может и есть другой подход, не через typyid, поэтому и спрашиваю
Re[7]: typeid.name() для наследуемого класса
От: 0xDEADBEEF Ниоткуда  
Дата: 27.10.05 20:02
Оценка: 1 (1)
Здравствуйте, V.I.P., Вы писали:

VIP>Здравствуйте, 0xDEADBEEF,


VIP>Я конечно благадорен тебе за помощь, но че орем то??

Ну... во-первых, я устал. Конец дня... и человек который долбит что у него задача.
Во-вторых твой ник. Very? Imbecilous? Pervert? Правильно?
И я устал. И долбит... В общем, не сдержался, в чем покорно прошу извинить.

VIP>я же знаю, может и есть другой подход, не через typyid, поэтому и спрашиваю

Впрочем, час за рулем — лучший транквилизатор. Я резко подобрел.
Вот тебе еще один подход.

#define START_STOP_LOGGER \
   struct l { \
      l()  { std::cout << "created   " << typeid(*this).name() << std::endl; } \
      ~l() { std::cout << "destroyed " << typeid(*this).name() << std::endl; } \
   } logger_logger_logger

struct A {
   START_STOP_LOGGER;
};

struct B:A {
   START_STOP_LOGGER;
};

int main()
{
   A a;
   std::cout << "----------------------\n";
   B b;
   std::cout << "done........\n";
}

в итоге получишь что-то вроде:

created A::l (создался a)
----------------
created A::l (создание b в процессе...)
created B::l (создался b)
done...............
destroyed B::l (уничтожается b)
destroyed A::l (закончилось уничтожение b)
destroyed A::l (уничтожается a)

Как убирать "лишние" A::l рассказывать не буду. Подумай сам хорошенько.
__________
16.There is no cause so right that one cannot find a fool following it.
Re: typeid.name() для наследуемого класса
От: kaa_t Россия  
Дата: 27.10.05 22:23
Оценка: 1 (1)
Здравствуйте, V.I.P., Вы писали:

VIP>Здравствуйте, подскачите пожалуйста

VIP>как узнать в базовом классе, имя класса наледуемого от него, т.е.

Можно,например так.


template<class T>
class base
{
        public:
        base(){ cout << typeid(T).name() <<endl; }
};


class class1 : base<class1>
{
};

class class2 : base<class2>
{
};


int main(int argc, char* argv[])
{
  class1 a;
  class2 b;

  return 0;
}
Re[2]: typeid.name() для наследуемого класса
От: kaa_t Россия  
Дата: 27.10.05 23:22
Оценка: 16 (3)
Здравствуйте, kaa_t, Вы писали:

Еще вариант


class base
{
        public:
        template<class T>
        base( T *){ cout << typeid(T).name() <<endl; }
};



class class1: base
{
        public:
        A():base(this){}
};

class class2 : base
{
        public:
        B():base(this){}
};

int main(int argc, char* argv[])
{
  class1 a;
  class2 b;

  return 0;
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.