65,187
社区成员




#include <iostream>
#include <string.h>
using namespace std;
class Base
{
public:
virtual void fun(){ cout<<"base fun"<<endl;}
void is_virtual(){cout<<"base not virtual"<<endl;}
};
class Derived: public Base
{
public:
virtual void fun(){ cout<<"derived fun"<<endl;}
virtual void is_virtual(){cout<<"derived virtual"<<endl;}
};
void Print1(Base b)
{
b.fun();
}
void Print2(Base *p)
{
p->fun();
}
void Print3(Base &b)
{
b.fun();
}
int main()
{
Derived d;
Print1(d); //base fun //1 传值,创建了新Base对象,虚表指针由编译器初始化
Print2(&d); //derived fun //2 原对象,虚表指针指向Derived
Print3(d); //derived fun //3 原对象
cout<<"--------"<<endl;
Base *b = new Base();
memcpy(b, &d, sizeof(Base));
Print1(*b); //base fun //4 传值,新Base对象
Print2(b); //derived fun //5 原对象Base部分,虚表指针指向Derived
Print3(*b); //derived fun //6 原对象Base部分
cout<<"--------"<<endl;
d.Base::fun(); //base fun //7 Base命名空间寻址,编译器完成
cout<<"--------"<<endl;
Base *pb = NULL, *pb2=new Derived;
pb2->is_virtual(); //base not virtual //9 根据指针类型查找Base类命名空间该函数,为非虚函数,静态绑定
pb->is_virtual(); //base not virtual //8 非虚函数,静态绑定
b->is_virtual(); //base not virtual //10 非虚函数,静态绑定
cout<<"--------"<<endl;
d.is_virtual(); //derived virtual //11 在Derived对象内存中进行函数寻址
Derived *pd = new Derived;
pd->is_virtual(); //derived virtual //12 动态绑定,在Derived对象内存中进行函数寻址
d.Base::is_virtual(); //base not virtual //13 Base命名空间寻址,编译器完成
delete b;
delete pb2;
delete pd;
return 0;
}
int main()
{
Derived d;
//Base temp((Base&)d); //对象被切割了
//within Print1, temp.Base::fun() 因为temp的动态类型是Base
Print1(d);
// Derived* p = &d; Base* temp = p;
// temp->Derived::fun,因为temp的动态类型是Derived*,虽然静态类型(申明类型)为Base*
//指针传值, 动态绑定
Print2(&d);
// Base& temp = d;
// temp.Derived::fun,因为temp的动态类型是Derived,虽然静态类型(申明类型)为Base
Print3(d); //Base& temp;
cout<<"--------"<<endl;
Base *b = new Base();
//因为Base和Derived有相同的内存布局, 所以完成memcpy后,b的动态类型已经是Derived*, 因为它vptr已经指向了Derived的vtable
//这种用法很危险!!
memcpy(b, &d, sizeof(Base));
//到此完全上面的3种情况了,不解释了
Print1(*b); //base fun //4 传值,新Base对象
Print2(b); //derived fun //5 原对象Base部分,虚表指针指向Derived
Print3(*b); //derived fun //6 原对象Base部分
cout<<"--------"<<endl;
//显示调用,没有用动态绑定, 在编译时确定了
d.Base::fun(); //base fun //7 Base命名空间寻址,编译器完成
cout<<"--------"<<endl;
//pb,pb2的静态类型为Base*, pb2的动态类型为Derived*, pb没有动态类型,因为它并没有指向一个实例
Base *pb = NULL, *pb2=new Derived;
//is_virtual的调用者静态类型如果是Base, Base*, Base&,则没有静态绑定的
//is_virtual的调用者静态类型如果是Derived, Derived*, Derived&,则动态绑定, 编译插入了查找vtable的指令
pb2->is_virtual(); //base not virtual //9 根据指针类型查找Base类命名空间该函数,为非虚函数,静态绑定
pb->is_virtual(); //base not virtual //8 非虚函数,静态绑定
//b的静态类型为Base*
b->is_virtual(); //base not virtual //10 非虚函数,静态绑定
cout<<"--------"<<endl;
//d的静态类型为Derived
d.is_virtual(); //derived virtual //11 在Derived对象内存中进行函数寻址
Derived *pd = new Derived;
//pd的静态类型是Drived*
pd->is_virtual(); //derived virtual //12 动态绑定,在Derived对象内存中进行函数寻址
//所有显示调用都是静态绑定的!
d.Base::is_virtual(); //base not virtual //13 Base命名空间寻址,编译器完成