#include <iostream>
using std::cout;
using std::endl;class A
{
public:
virtual void foo1(){cout<<"A::foo1()"<<endl;}
private:
virtual void foo(){cout<<"A::foo()"<<endl;}
};class B:private A
{
private:
virtual void foo1(){cout<<"B::foo1()"<<endl;}
public:
virtual void foo(){cout<<"B::foo()"<<endl;}
};int main()
{
B b;
A *a=(A *)&b;
a->foo1();

A a1;
B *b1=(B *)&a1;
b1->foo(); return 0;
}
/*
The code above makes calls to private member via object pointer, pls explain why.This question is mentioned first in the following link, thank the original initiator.http://expert.csdn.net/Expert/topic/1307/1307940.xml?temp=.5337946
*/

解决方案 »

  1.   

    关键是看这一句:
    a->foo1();//现在a 的静态类型是A*,它实际指向的是一个B类型的对象.编译器看到a时只知道 a 是指向A类型对象的指针, 并不知道它指向的实际类型,于是编译器在class A中找成员函数fool(),它找到了,接着编译器检查成员函数fool()的访问控制权,发现class A 中的fool()是public,ok,可以访问!接着它又发现fool()是virtual function,于是编译器决定执行动态绑定,将this指针入栈,即将a的值入栈,而 a 的值就是b 的地址:&b,也就是说将 &b入栈,再通过&b找到vptr(vptr在对象中的位置由于编译器的具体实现决定),通过vptr找到vtable,vtable是一个指向虚函数的指针数组,通过虚函数名fool找到指向向fool函数的指针值,在通过这个指针调用实际的fool函数,也就是b.fool,这就是大名鼎鼎的"动态绑定",最关键的是此是不会再次检测实际调用的fool成员函数的访问控制权!也就是说,访问控制权只在编译期有作用,运行期没有作用,因为vtable里没有与访问控制权有关的信息,如果我们将这类信息加入vtable,并在运行时检查访问控制权,不仅会增加vtable的数据存储量,还会影响virtual function的运行效率,virtual function带来的负担已经让C++受到了一些人的指责了,如果再加上访问控制权的负担,将会使C++苦不堪言,再说,编译期已经检测了访问控制权,为何又要检查一次呢?如果出现楼主给出程序中的"异常",只能说明程序设计是怪异的.对于:B *b1=(B *)&a1;
    b1->foo();
    分析同上;
    在VC6.0中下面两个语句将出警告:
    A *a=(A *)&b;//原因是private 继承,它是一种"基于实现"的继承,不是"is-             //a"继承
    B *b1=(B *)&a1;
    因为这种类型转换是"粗暴"的,
    如果这样:
    A *a = reinterpret_cast<A *> (&b);
         B *b1 = reinterpret_cast<B *> (&a1); 
    就不会出现警告.
      

  2.   

    从这里明白了为何C++导师们都劝我们要用C++风格的类型转换而不要用C风格的。如果用C++风格的转换,就只有reinterpret_cast<>行得通,而且看起来极不顺眼,大家都知道那是危险的。而用C风格的转型,MingW上居然连一个warning都没有!如果是在一个实际的系统里,查错不把你查死才怪呢。
      

  3.   

    "...发现class A 中的fool()是public,ok,可以访问!接着它又发现fool()是virtual function,于是编译器决定执行动态绑定,将this指针入栈..."说得真好,学习
      

  4.   

    #include <iostream>
    using std::cout;
    using std::endl;class A
    {
    public:
    /*virtual*/ void foo1(){cout<<"A::foo1()"<<endl;}
    private:
    /*virtual*/ void foo(){cout<<"A::foo()"<<endl;}
    };class B : private A
    {
    private:
    /*virtual*/ void foo1(){cout<<"B::foo1()"<<endl;}
    public:
    /*virtual*/ void foo(){cout<<"B::foo()"<<endl;}
    };int main()
    {
    B b;
    A *a=reinterpret_cast<A *>(&b);
    a->foo1();

    A a1;
    B *b1=reinterpret_cast<B *>(&a1);
    b1->foo(); return 0;
    }/*
    如果去掉Virtual结果又是怎样?去掉Virtual便进行早绑定output (vc6):
    A::foo1()
    B::foo()
    Press any key to continue
    */