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

, а для расширения мировоззрения

.