определить указатель является ли классом Х
От: maks1180  
Дата: 08.09.11 22:57
Оценка:
class BASE;
class A1 : BASE;
class A2 : BASE;

Есть указатель
BASE* ptr;

Как можно определить, является ли ptr указателем на класс A1 или A2 ?
P.S. На ассеблеме мне кажеться, что это можно сделать если сравнить v-table ptr и A1 и A2.
===============================================
(реклама, удалена модератором)
Re: определить указатель является ли классом Х
От: warhast Россия  
Дата: 08.09.11 23:14
Оценка:
M>Как можно определить, является ли ptr указателем на класс A1 или A2 ?
M>P.S. На ассеблеме мне кажеться, что это можно сделать если сравнить v-table ptr и A1 и A2.

dynamic_cast<>

Вроде оно как раз vtbl-ы и сравнивает.
Re[2]: определить указатель является ли классом Х
От: maks1180  
Дата: 09.09.11 01:28
Оценка: :)
W>dynamic_cast<>

W>Вроде оно как раз vtbl-ы и сравнивает.


dynamic_cast
1) требует RTTI
2) очень тяжелая функция, в дебагере видел кучу вызовов процедур.

Мне нужно быстро сравнить.
===============================================
(реклама, удалена модератором)
Re: определить указатель является ли классом Х
От: st0nx  
Дата: 09.09.11 04:19
Оценка:
Здравствуйте, maks1180, Вы писали:

M>class BASE;

M>class A1 : BASE;
M>class A2 : BASE;

M>Есть указатель

M>BASE* ptr;

M>Как можно определить, является ли ptr указателем на класс A1 или A2 ?

M>P.S. На ассеблеме мне кажеться, что это можно сделать если сравнить v-table ptr и A1 и A2.


#include <iostream>
#include <typeinfo>

using namespace std;

class BASE {virtual void vvfunc() {}};
class A1 : public BASE { };
class A2 : public BASE { };


int main() {

  BASE *b1,*b2;
  b1 = new A1;
  b2 = new A2;


    cout << typeid(*b1).name() << endl;
    cout << typeid(*b2).name() << endl;

  return 0;
}
Re: определить указатель является ли классом Х
От: c-smile Канада http://terrainformatica.com
Дата: 09.09.11 05:33
Оценка:
Здравствуйте, maks1180, Вы писали:

Пишем так:

class BASE
{
public:
  virtual uint_ptr  type_id() const { return 0; }
  template <typename OT>
      bool is_of_type() const { return type_id() == OT::class_id(); } 
};

#define DEFINE_TYPE_ID \
   static  uint_ptr  class_id() { static int d = 0; return (uint_ptr)&d; } \
   virtual uint_ptr  type_id() const { return class_id(); }

class A1 : BASE
{
  DEFINE_TYPE_ID  
  ...
};
class A2 : BASE
{
  DEFINE_TYPE_ID
  ...
};


пользуем так:

BASE* ptr;

if( ptr->is_of_type<A1>() ) ...
if( ptr->is_of_type<A2>() ) ...
Re[2]: определить указатель является ли классом Х
От: Кодт Россия  
Дата: 09.09.11 06:15
Оценка:
Здравствуйте, c-smile, Вы писали:

MFC-RTTI reloaded
С той разницей, что твой код проверяет на строгое соответствие фактического типа формальному, а по-честному было бы — в соответствие с заветами Барбары Лисков — проверять наследие.

template<class T>
bool is_of_type<T>() const { return is_of_type(T::class_id()); }

bool is_of_type(ClassID id) const { return id==type_id() || __super::is_of_type(id); } // где __super вводится в макросе или компилятором

Либо без рекурсии, забегом по дереву метаданных. (Здесь метаданные примитивны — уникальное число-указатель; а могут быть весьма богатыми).

В общем-то, dynamic_cast делает примерно это же, только поддерживает все фичи языка — множественное, виртуальное, непубличное наследование.
Потому он и увесистый такой.
Перекуём баги на фичи!
Re[2]: определить указатель является ли классом Х
От: maks1180  
Дата: 09.09.11 10:44
Оценка:
Получается сравнение с вызовом трех ф-ций.
Мне нужно очень быстро сравнивать, поэтому не приемлемое решение для меня.
Как сделать так
1) получить поинтер на v-table для A1, A2
2) получить поинтер на v-table для переменной ptr. Я подозреваю, что-то типо этого (void*)(*((int*)ptr)). Т.к. узазатель на v-table должен быть первым.
3) сравнить поинтеры на v-table.

Как сделать первый пункт ?
===============================================
(реклама, удалена модератором)
Re[3]: определить указатель является ли классом Х
От: warhast Россия  
Дата: 09.09.11 10:53
Оценка:
Здравствуйте, maks1180, Вы писали:

M>Получается сравнение с вызовом трех ф-ций.

M>Мне нужно очень быстро сравнивать, поэтому не приемлемое решение для меня.

Вариант: virtual int WhoAmI () { return какой-то-ИД-класса; }
Re[4]: определить указатель является ли классом Х
От: rus blood Россия  
Дата: 09.09.11 15:09
Оценка:
Здравствуйте, warhast, Вы писали:

W>Вариант: virtual int WhoAmI () { return какой-то-ИД-класса; }


А зачем виртуальные функции и пр.?

Если уж можно "ломать" класс BASE, то завести в нем поле — идентификатор класса.
Каждый производный класс пишет туда свой ID в конструкторе.
Простой (невиртуальный) метод базового класса возвращает идентификатор.
Имею скафандр — готов путешествовать!
Re[5]: определить указатель является ли классом Х
От: warhast Россия  
Дата: 09.09.11 15:32
Оценка:
RB>А зачем виртуальные функции и пр.?

RB>Если уж можно "ломать" класс BASE, то завести в нем поле — идентификатор класса.

RB>Каждый производный класс пишет туда свой ID в конструкторе.
RB>Простой (невиртуальный) метод базового класса возвращает идентификатор.

Судя по http://tinodidriksen.com/2010/04/14/cpp-dynamic-cast-performance/ — особой разницы нет, особенно если надо не только узнать тип объекта, но и что-то с этим объектом сделать. А там, возможно, даже скорости dynamic_cast окажется вполне достаточно, чтобы не думать об оптимизациях именно перекастовывания указателей.
Re[3]: определить указатель является ли классом Х
От: c-smile Канада http://terrainformatica.com
Дата: 09.09.11 16:18
Оценка:
Здравствуйте, maks1180, Вы писали:

M>Получается сравнение с вызовом трех ф-ций.

M>Мне нужно очень быстро сравнивать, поэтому не приемлемое решение для меня.
M>Как сделать так
M>1) получить поинтер на v-table для A1, A2
M>2) получить поинтер на v-table для переменной ptr. Я подозреваю, что-то типо этого (void*)(*((int*)ptr)). Т.к. узазатель на v-table должен быть первым.
M>3) сравнить поинтеры на v-table.

Пробовал. Обнаружил очень интересные факты про жизнь vtbl и оптимизацию пстроения оных в компайлерах.
Вплоть до того что вообще vtbl не строится в отдельных случаях.
Короче туда-не-ходи-снег-бащка-попадет.

M>Как сделать первый пункт ?


Нарисуй нечто простое типа:

struct base
{
  int dummy;
  virtual ~base() { dummy = 0; }
};


sizeof(base) и offsetof(dummy,base) дадут тебе полную картину где по отношению к адресу this лежит vtbl.
Re[5]: определить указатель является ли классом Х
От: maks1180  
Дата: 09.09.11 17:31
Оценка:
RB>Если уж можно "ломать" класс BASE, то завести в нем поле — идентификатор класса.
RB>Каждый производный класс пишет туда свой ID в конструкторе.
RB>Простой (невиртуальный) метод базового класса возвращает идентификатор.

Недостатки виртуальной ф-ции — скорость ниже
Недостатки переменной — память.

Интересно, как получить указатель на v-table для класса ?
===============================================
(реклама, удалена модератором)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.