К вопросу о вопросах по C++
31/1/06 13:16Продолжаем набивать журнал контентом.
Что будет, если указателю на функцию-член присвоить указатель на виртуальный метод предка, а потом вызвать её на экземпляре потомка?
А для невиртуальной функции?
И на gcc, и на MSVC выдаёт одно и то же:
Вывод интересен: указатель на функцию-член хранит И индекс в VMT, И указатель на функцию. Ну и флаг, указывающий, что именно хранится.
Что будет, если указателю на функцию-член присвоить указатель на виртуальный метод предка, а потом вызвать её на экземпляре потомка?
А для невиртуальной функции?
#include <iostream>
class A
{
public:
virtual void f() { std::cout << "A::f()\n"; };
void g() { std::cout << "A::g()\n"; };
};
class B : public A
{
public:
virtual void f() { std::cout << "B::f()\n"; };
void g() { std::cout << "B::g()\n"; };
};
typedef void (A::*VirtualFunctionPointer) ();
int main()
{
A a;
B b;
B* pb = &b;
VirtualFunctionPointer p = &A::f;
(pb->*p) ();
p = &A::g;
(pb->*p) ();
return 0;
}
И на gcc, и на MSVC выдаёт одно и то же:
B::f()
A::g()Вывод интересен: указатель на функцию-член хранит И индекс в VMT, И указатель на функцию. Ну и флаг, указывающий, что именно хранится.
Tags:
(no subject)
31/1/06 03:26 (UTC)fun
1/2/06 06:37 (UTC)Ко всему, еще есть одна особенность, насколько я знаю, указатель на функцию-член имеет жесткую привязку к типу(классу) в котором эта функция описана, но в этом примере в первом случае вызов (pb->*p) (); эквивалентен B::f()(так как B наследник класса A), т.е. можно сказать, что сработал механизм преобразования имени виртуальной функции в индекс в виртуальной таблице. Для второго присваивания все более проще, при присваивании p = &A::g, а сам p является просто "указателем" на функции-члены класса A и только A, то поэтому и произошел вызов функции A::g(), причем его скорее всего можно интерпритировать как pb->A::g();
P.S. Все вышенаписанное сугубо мое ИМХО :-)
(no subject)
1/2/06 06:42 (UTC)(no subject)
1/2/06 06:52 (UTC)(no subject)
1/2/06 06:53 (UTC)(no subject)
1/2/06 07:20 (UTC)(no subject)
1/2/06 07:52 (UTC)P.S. наверно я вас достал своими постами, звыняйте... :-)
(no subject)
3/2/09 12:31 (UTC)(no subject)
24/4/10 07:29 (UTC)//VirtualFunctionPointer p = &A::f; //BEGIN
:004012AA 8B05A4A04000 mov eax, dword ptr [0040A0A4]
//mov [p],eax //И
:004012B0 890578C74000 mov dword ptr [0040C778], eax
:004012B6 8B05A8A04000 mov eax, dword ptr [0040A0A8]
//mov [p+0x4],eax //И
:004012BC 89057CC74000 mov dword ptr [0040C77C], eax
:004012C2 8B05ACA04000 mov eax, dword ptr [0040A0AC]
//mov [p+0x8],eax //И
:004012C8 890580C74000 mov dword ptr [0040C780], eax
//VirtualFunctionPointer p = &A::f; //END
//(pb->*p) ();
:004012CE FF75D0 push [ebp-30]
:004012D1 FF1578C74000 call dword ptr [0040C778]
:004012D7 59 pop ecx
//....
//(pb->*p) ();
:004012D8 FF75CC push [ebp-34]
:004012DB FF1578C74000 call dword ptr [0040C778]
:004012E1 59 pop ecx