Есть класс наследованный от CObject. Нужно вызвать виртуальный метод этого класса, не имея экземпляра класса (этот метод не использует this). Как это сделать?
Понимаю, что нужно каким-то образом получить vtbl этого класса и найти в нём смещение нужного метода... Но вот как?
А нужно что-то вроде:
class CAssert
{
public:
template<class class_name, class objectT>
void KindOf(objectT* pObject)
{ ASSERT(pObject->IsKindOf( ((class_name*)NULL)->GetRuntimeClass() )); }
// только это не работает
};
Естественно это не работает. Разыменовывать нулевые указатели запрещено.
Лучше всего — отказаться от убогой информации о типе времени выполнения на методах из кайнд оф и перейти к стандартному typeid.
Здравствуйте, Vamp, Вы писали:
V>Естественно это не работает. Разыменовывать нулевые указатели запрещено. V>Лучше всего — отказаться от убогой информации о типе времени выполнения на методах из кайнд оф и перейти к стандартному typeid.
Не, RTTI не катит.
Здравствуйте, korzhik, Вы писали:
K>про виртуальную функцию не понял, а чтобы вышеприведённый кусок кода заработал, пиши так:
Вызвать вирутальную функцию с this = абы_шо, т.е. недействительный экземпляр. K>
Здравствуйте, Chez, Вы писали:
C>В шаблоне это работать не будет. C>Макрос RUNTIME_CLASS(class_name) разворачиватся в ...class##class_name... В результате ошибка C>
C>error C2039: 'classclass_name' : is not a member of 'CWnd'
да, действительно
что то сразу не сообразил, что у вас там шаблон
ну что ж будем думать...
Здравствуйте, 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 метод.
JS>что за глупости? какой виртуальный метод если объекта нет? Насколько я понял тебе нужен просто static метод.
Это не static метод, в том то всё и дело, а virtual. Но я хотел бы его вызвать, будто бы он static.
Замечу ещё раз, что код этого метода не используетthis.
Здравствуйте, 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 не нужен.
Chez wrote:
> JS>что за глупости? какой виртуальный метод если объекта нет? Насколько я понял тебе нужен просто static метод. > Это не static метод, в том то всё и дело, а virtual. Но я хотел бы его вызвать, будто бы он static. > Замечу ещё раз, что код этого метода не используетthis.
А что это за метод (вообще, в c++ не существует методов, только ф-ции-члены ), кто его создатель — ты или творцы MFC?
Это МФСишное убожество времент 4 версии компилятора визуал си.
А что значит "в c++ не существует методов, только ф-ции-члены"? Функции-члены в С++ и называются методами. Или сообщениями даже
Здравствуйте, MaximE, Вы писали:
ME>Chez wrote:
>> JS>что за глупости? какой виртуальный метод если объекта нет? Насколько я понял тебе нужен просто static метод. >> Это не static метод, в том то всё и дело, а virtual. Но я хотел бы его вызвать, будто бы он static. >> Замечу ещё раз, что код этого метода не используетthis.
ME>А что это за метод (вообще, в c++ не существует методов, только ф-ции-члены ), кто его создатель — ты или творцы MFC?
Ну ты просто гений. в c++ не существует ни методов ни функций членов, поскольку стандарт на английском писан. так что же теперь по русски не разговаривать?
ME>-- ME>Maxim Yegorushkin
Здравствуйте, 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;
}
ME>А что это за метод (вообще, в c++ не существует методов, только ф-ции-члены ), кто его создатель — ты или творцы MFC?
ME>-- ME>Maxim Yegorushkin
Творцы MFC. CObject::GetRuntimeClass
Здравствуйте, <Аноним>, Вы писали:
А>Виртуальные метод так вызвать нельзя, потому что виртуальных методов "не использующих this" не существует. this используется реализацией вызова виртуального метода, так как необходимо обратиться к виртуальной таблице, ссылка на которую находится в теле объекта и на нее указывает this. Через (class_name*)NULL можно вызвать невиртуальный метод, не использующий this. Тогда, правда, такой метод следовало бы сделать статическим, раз ему this не нужен.
Ну почему же нет? Машинный код виртуального метода ничем не отличается от обычной функции. Нужно только определить, где в памяти находится этот метод и вызвать его, в параметре EBX указав 0 (this — не используется).
Я знаю, что это возможно, но не знаю как. Догадываюсь, что нужно что-то мутить с vtbl.
Здравствуйте, Кодт, Вы писали:
К>Уже сама по себе виртуальность использует this.
Вот я и думаю если туда подсунуть какой-нить суррогатный this... К>А тебе, видимо, нужно другое: виртуальный метод адресации к статическому
Я бы это обязательно добавил, если бы проектировал MFC.
GetRuntimeClass() — виртуальный, и статического аналога нет
Chez, ICQ# 161095094
Re[3]: аноним 2
От:
Аноним
Дата:
19.10.04 09:07
Оценка:
C>Ну почему же нет? Машинный код виртуального метода ничем не отличается от обычной функции. Нужно только определить, где в памяти находится этот метод и вызвать его, в параметре EBX указав 0 (this — не используется).
Здравствуйте, 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;