#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
*/
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
*/
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);
就不会出现警告.
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
*/