Вызов виртуального метода для класса
От: Chez Россия  
Дата: 19.10.04 07:24
Оценка: :)
Есть класс наследованный от CObject. Нужно вызвать виртуальный метод этого класса, не имея экземпляра класса (этот метод не использует this). Как это сделать?

Понимаю, что нужно каким-то образом получить vtbl этого класса и найти в нём смещение нужного метода... Но вот как?

А нужно что-то вроде:
class CAssert
{
public:
    template<class class_name, class objectT>
    void KindOf(objectT* pObject)
    { ASSERT(pObject->IsKindOf( ((class_name*)NULL)->GetRuntimeClass() )); }
                                        // только это не работает
};


Помогите плз
Chez, ICQ# 161095094
Re: Вызов виртуального метода для класса
От: Vamp Россия  
Дата: 19.10.04 07:29
Оценка:
Естественно это не работает. Разыменовывать нулевые указатели запрещено.
Лучше всего — отказаться от убогой информации о типе времени выполнения на методах из кайнд оф и перейти к стандартному typeid.
Да здравствует мыло душистое и веревка пушистая.
Re[2]: Вызов виртуального метода для класса
От: Chez Россия  
Дата: 19.10.04 07:34
Оценка:
Здравствуйте, Vamp, Вы писали:

V>Естественно это не работает. Разыменовывать нулевые указатели запрещено.

V>Лучше всего — отказаться от убогой информации о типе времени выполнения на методах из кайнд оф и перейти к стандартному typeid.
Не, RTTI не катит.
Chez, ICQ# 161095094
Re[3]: Вызов виртуального метода для класса
От: Lorenzo_LAMAS  
Дата: 19.10.04 07:37
Оценка: :)
C>Не, RTTI не катит.

Вызывать нестатическую функцию-член без объекта тоже никуда не катит.
Of course, the code must be complete enough to compile and link.
Re: Вызов виртуального метода для класса
От: korzhik Россия  
Дата: 19.10.04 07:38
Оценка: +1
Здравствуйте, Chez, Вы писали:

C>
C>class CAssert
C>{
C>public:
C>    template<class class_name, class objectT>
C>    void KindOf(objectT* pObject)
C>    { ASSERT(pObject->IsKindOf( ((class_name*)NULL)->GetRuntimeClass() )); }
C>                                        // только это не работает
C>};
C>


про виртуальную функцию не понял, а чтобы вышеприведённый кусок кода заработал, пиши так:
//...
{ ASSERT(pObject->IsKindOf( RUNTIME_CLASS(class_name)); }
Re[2]: Вызов виртуального метода для класса
От: Chez Россия  
Дата: 19.10.04 07:44
Оценка:
Здравствуйте, korzhik, Вы писали:

K>про виртуальную функцию не понял, а чтобы вышеприведённый кусок кода заработал, пиши так:

Вызвать вирутальную функцию с this = абы_шо, т.е. недействительный экземпляр.
K>
K>//...
K>{ ASSERT(pObject->IsKindOf( RUNTIME_CLASS(class_name)); }
K>

В шаблоне это работать не будет.
Макрос RUNTIME_CLASS(class_name) разворачиватся в ...class##class_name... В результате ошибка

error C2039: 'classclass_name' : is not a member of 'CWnd'

Chez, ICQ# 161095094
Re[3]: Вызов виртуального метода для класса
От: korzhik Россия  
Дата: 19.10.04 07:46
Оценка:
Здравствуйте, Chez, Вы писали:

C>В шаблоне это работать не будет.

C>Макрос RUNTIME_CLASS(class_name) разворачиватся в ...class##class_name... В результате ошибка
C>

C>error C2039: 'classclass_name' : is not a member of 'CWnd'


да, действительно
что то сразу не сообразил, что у вас там шаблон
ну что ж будем думать...
Re: Вызов виртуального метода для класса
От: JakeS  
Дата: 19.10.04 07:48
Оценка:
Здравствуйте, Chez, Вы писали:

C>Есть класс наследованный от CObject. Нужно вызвать виртуальный метод этого класса, не имея экземпляра класса (этот метод не использует this). Как это сделать?


C>Понимаю, что нужно каким-то образом получить vtbl этого класса и найти в нём смещение нужного метода... Но вот как?


C>А нужно что-то вроде:

C>
C>class CAssert
C>{
C>public:
C>    template<class class_name, class objectT>
C>    void KindOf(objectT* pObject)
C>    { ASSERT(pObject->IsKindOf( ((class_name*)NULL)->GetRuntimeClass() )); }
C>                                        // только это не работает
C>};
C>


C>Помогите плз


что за глупости? какой виртуальный метод если объекта нет? Насколько я понял тебе нужен просто static метод.
Re[2]: Вызов виртуального метода для класса
От: Chez Россия  
Дата: 19.10.04 07:52
Оценка:
JS>что за глупости? какой виртуальный метод если объекта нет? Насколько я понял тебе нужен просто static метод.
Это не static метод, в том то всё и дело, а virtual. Но я хотел бы его вызвать, будто бы он static.
Замечу ещё раз, что код этого метода не использует this.
Chez, ICQ# 161095094
Re: Вызов виртуального метода для класса
От: Аноним  
Дата: 19.10.04 08:10
Оценка: +1
Здравствуйте, Chez, Вы писали:

C>Есть класс наследованный от CObject. Нужно вызвать виртуальный метод этого класса, не имея экземпляра класса (этот метод не использует this). Как это сделать?


C>Понимаю, что нужно каким-то образом получить vtbl этого класса и найти в нём смещение нужного метода... Но вот как?


C>А нужно что-то вроде:

C>
C>class CAssert
C>{
C>public:
C>    template<class class_name, class objectT>
C>    void KindOf(objectT* pObject)
C>    { ASSERT(pObject->IsKindOf( ((class_name*)NULL)->GetRuntimeClass() )); }
C>                                        // только это не работает
C>};
C>


C>Помогите плз


Виртуальные метод так вызвать нельзя, потому что виртуальных методов "не использующих this" не существует. this используется реализацией вызова виртуального метода, так как необходимо обратиться к виртуальной таблице, ссылка на которую находится в теле объекта и на нее указывает this. Через (class_name*)NULL можно вызвать невиртуальный метод, не использующий this. Тогда, правда, такой метод следовало бы сделать статическим, раз ему this не нужен.
Re[3]: Вызов виртуального метода для класса
От: MaximE Великобритания  
Дата: 19.10.04 08:12
Оценка:
Chez wrote:

> JS>что за глупости? какой виртуальный метод если объекта нет? Насколько я понял тебе нужен просто static метод.

> Это не static метод, в том то всё и дело, а virtual. Но я хотел бы его вызвать, будто бы он static.
> Замечу ещё раз, что код этого метода не использует this.

А что это за метод (вообще, в c++ не существует методов, только ф-ции-члены ), кто его создатель — ты или творцы MFC?

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 gamma
Re[4]: Вызов виртуального метода для класса
От: Vamp Россия  
Дата: 19.10.04 08:17
Оценка:
Это МФСишное убожество времент 4 версии компилятора визуал си.
А что значит "в c++ не существует методов, только ф-ции-члены"? Функции-члены в С++ и называются методами. Или сообщениями даже
Да здравствует мыло душистое и веревка пушистая.
Re[4]: Вызов виртуального метода для класса
От: JakeS  
Дата: 19.10.04 08:21
Оценка: :)
Здравствуйте, MaximE, Вы писали:

ME>Chez wrote:


>> JS>что за глупости? какой виртуальный метод если объекта нет? Насколько я понял тебе нужен просто static метод.

>> Это не static метод, в том то всё и дело, а virtual. Но я хотел бы его вызвать, будто бы он static.
>> Замечу ещё раз, что код этого метода не использует this.

ME>А что это за метод (вообще, в c++ не существует методов, только ф-ции-члены ), кто его создатель — ты или творцы MFC?


Ну ты просто гений. в c++ не существует ни методов ни функций членов, поскольку стандарт на английском писан. так что же теперь по русски не разговаривать?

ME>--

ME>Maxim Yegorushkin
Re[3]: Вызов виртуального метода для класса
От: Кодт Россия  
Дата: 19.10.04 08:30
Оценка:
Здравствуйте, Chez, Вы писали:

JS>>что за глупости? какой виртуальный метод если объекта нет? Насколько я понял тебе нужен просто static метод.

C>Это не static метод, в том то всё и дело, а virtual. Но я хотел бы его вызвать, будто бы он static.
C>Замечу ещё раз, что код этого метода не использует this.

Уже сама по себе виртуальность использует this.

А тебе, видимо, нужно другое: виртуальный метод адресации к статическому
typedef int (*Fun)(int);

class Foo
{
public:
  virtual Fun have_fun() const { return my_fun; }
private:
  static int my_fun(int x) { return x*2; }
};

class Bar : public Foo
{
public:
  Fun have_fun() const { return my_own_fun; }
private:
  static int my_own_fun(int x) { return x*x; }
};

void test_fun(Fun fun)
{
  cout << fun(10) << endl;
}

void test_obj(Foo* p)
{
  test_fun(p->have_fun());
}

main()
{
  Foo *a = new Foo(), *b = new Bar();
  test_obj(a);
  test_obj(b);
  delete a; delete b;
}
Перекуём баги на фичи!
Re[5]: Вызов виртуального метода для класса
От: MaximE Великобритания  
Дата: 19.10.04 08:43
Оценка:
Vamp wrote:

> А что значит "в c++ не существует методов, только ф-ции-члены"? Функции-члены в С++ и называются методами. Или сообщениями даже


http://groups.google.com/groups?threadm=bisnp7%24a4k%241%40hercules.btinternet.com

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 gamma
Re[4]: Вызов виртуального метода для класса
От: Chez Россия  
Дата: 19.10.04 09:00
Оценка:
ME>А что это за метод (вообще, в c++ не существует методов, только ф-ции-члены ), кто его создатель — ты или творцы MFC?

ME>--

ME>Maxim Yegorushkin
Творцы MFC. CObject::GetRuntimeClass
Chez, ICQ# 161095094
Re[2]: Вызов виртуального метода для класса
От: Chez Россия  
Дата: 19.10.04 09:00
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Виртуальные метод так вызвать нельзя, потому что виртуальных методов "не использующих this" не существует. this используется реализацией вызова виртуального метода, так как необходимо обратиться к виртуальной таблице, ссылка на которую находится в теле объекта и на нее указывает this. Через (class_name*)NULL можно вызвать невиртуальный метод, не использующий this. Тогда, правда, такой метод следовало бы сделать статическим, раз ему this не нужен.


Ну почему же нет? Машинный код виртуального метода ничем не отличается от обычной функции. Нужно только определить, где в памяти находится этот метод и вызвать его, в параметре EBX указав 0 (this — не используется).

Я знаю, что это возможно, но не знаю как. Догадываюсь, что нужно что-то мутить с vtbl.
Chez, ICQ# 161095094
Re[4]: Вызов виртуального метода для класса
От: Chez Россия  
Дата: 19.10.04 09:04
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Уже сама по себе виртуальность использует this.

Вот я и думаю если туда подсунуть какой-нить суррогатный this...
К>А тебе, видимо, нужно другое: виртуальный метод адресации к статическому
Я бы это обязательно добавил, если бы проектировал MFC.
GetRuntimeClass() — виртуальный, и статического аналога нет
Chez, ICQ# 161095094
Re[3]: аноним 2
От: Аноним  
Дата: 19.10.04 09:07
Оценка:
C>Ну почему же нет? Машинный код виртуального метода ничем не отличается от обычной функции. Нужно только определить, где в памяти находится этот метод и вызвать его, в параметре EBX указав 0 (this — не используется).

Чтоб найти втбл как раз this и нужен.
Re[3]: Вызов виртуального метода для класса
От: Аноним  
Дата: 19.10.04 09:13
Оценка: 4 (2) +1
Здравствуйте, Chez, Вы писали:

C>Здравствуйте, <Аноним>, Вы писали:


А>>Виртуальные метод так вызвать нельзя, потому что виртуальных методов "не использующих this" не существует. this используется реализацией вызова виртуального метода, так как необходимо обратиться к виртуальной таблице, ссылка на которую находится в теле объекта и на нее указывает this. Через (class_name*)NULL можно вызвать невиртуальный метод, не использующий this. Тогда, правда, такой метод следовало бы сделать статическим, раз ему this не нужен.


C>Ну почему же нет? Машинный код виртуального метода ничем не отличается от обычной функции. Нужно только определить, где в памяти находится этот метод и вызвать его, в параметре EBX указав 0 (this — не используется).


C>Я знаю, что это возможно, но не знаю как. Догадываюсь, что нужно что-то мутить с vtbl.


Я ж говорю — vtbl можно найти только если есть объект, т.к. его тело содержит ссылку на нее. Если нужно невиртуально вызвать метод, объявленный виртуальным, то в вызове нужно явно указать имя класса:


struct C1
{
virtual int Met() { return 1; }
};

struct C2 : public C1
{
virtual int Met() { return 2; }
};


int _tmain(int argc, _TCHAR* argv[])
{
// эти два вызова работают: невиртуальный вызов виртуальной функции
int i2=((C2*)0)->C2::Met();
int i1=((C2*)0)->C1::Met();
assert( i2==2);
assert( i1==1);

int ifail=((C2*)0)->Met(); // здесь падает: виртуальный вызов через null-указатель
return 0;


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