Здравствуйте.
Когда-то я наступил на грабли множественного наследования. А сегодня, вспомнив об этом,
хочу подсунуть их вам, подогреть, так сказать, форум.
Ниже приведены три класса: два базовых и один их наследник
class A{
public:
int a;
};
class B{
public:
int b;
};
class C:public A,public B
{
public:
void Test(){
cout<<"a:"<<a<<" b:"<<b;
}
};
Теперь выполняем сей код:
int main(int argc, char* argv[])
{
typedef void (B::*pClassB_Func)();
C TestC; //Итак, имеем класс C - наследник A+B
TestC.a=1; //Это поле от A
TestC.b=2; //Это поле от B
pClassB_Func pf=static_cast<pClassB_Func>(C::Test); //Указатель на функцию void C::Test()
//Вот это, казалось бы безобидный вариант. Но неправильный
B * pB=&TestC;
(pB->*pf)();
//Вот это очень ужасный на вид, но РАБОЧИЙ вариант
pB=static_cast<B*>((void*)&TestC);
(pB->*pf)();
return 0;
}
Попробуйте предсказать, что выдаст функция в первом и втором варианте.
Кому в лом это компилить, скажу что первый вариант вызова функции выдаст что-то типа
"a:2 b:1234567". Т.е. адресация СДВИНУЛАСЬ на размер класса A, и поле a теперь на самом деле попадает на поле b, а поле b — сами видите куда.
Во втором случае все прекрасно.
Пораскинув мозгами, поведение компилятора можно понять: мы просили указатель на базовый класс B, он нам его и дал, слегка сместив. Во втором случае имеем передачу адреса (void*), и компилятор послушно ее выполняет.
Ответа я, собственно, не прошу. Просто хочу показать фишку. Ни в одном учебнике по С++, что я читал, такого примера не встречал, так что может кому сберегу лоб (см грабли)
Если у кого есть похожие байки, или он хочет чё-нить выразить по поводу сабжа, или хочет назвать меня ослом, буду рад выслушать