voidBase::baseFunc(){ printf("This is Base::baseFunc(no virtual), x = %d\n", x); } voidBase::vfunc1(){ printf("This is Base::vfunc1(virtual), x = %d\n", x); } voidBase::vfunc2(){ printf("This is Base::vfunc2(virtual), x = %d\n", x); }
voidDerived::derivedFunc(){ printf("This is Derived::derivedFunc(no virtual), y = %d\n", y); } voidDerived::vfunc1(){ printf("This is Derived::vfunc1(virtual), y = %d\n", y); } voidDerived::vfunc3(){ printf("This is Derived::vfunc3(virtual), y = %d\n", y); }
首先看下两个类大致的一个对象模型
我们知道,在C++中要利用多态的性质必须利用指针或引用实现
1 2 3 4 5
Base *base = new Derived; base->vfunc1(); // 调用Derived::vfunc1() base->vfunc2(); // 调用Base::vfunc2() // base->vfunc3(); error: 'class Base' has no member named 'vfunc3' // base->derivedFunc(); error: 'class Base' has no member named 'derivedFunc'
// Base类的非多态方法 void (*baseFunc)(struct Base *const); };
// 对于所有non static的成员函数,在C++中都会隐式的给参数列表中加上一个指向自己的指针,并且不能赋给该指针其他对象。 voidbaseFunc(struct Base *constthis){ printf("This is Base Function(no virtual), x = %d\n", this->x); } // 由于C语言无法重载,所以将vfunc后面加上后缀来表明是谁的虚函数 voidvfunc1_base(struct Base *constthis){ printf("This is Base::vfunc1(virtual), x = %d\n", this->x); } voidvfunc2_base(struct Base *constthis){ printf("This is Base::vfunc2(virtual), x = %d\n", this->x); }
intmain(){ structBase *ptr = (struct Base *) newDerived(10); ptr->baseFunc(ptr); // 因为虚表中存的是void *类型,所以要强制转换类型成函数指针。 // vfunc1_derived() ((void (*)(struct Base *)) ((ptr->vptr)[0]))(ptr); // vfunc2_base() ((void (*)(struct Base *)) ((ptr->vptr)[1]))(ptr); // 实际在C++中无法访问到vfunc3_derived(),但在这里可以,可以考虑下原因。 // vfunc3_derived() ((void (*)(struct Base *)) ((ptr->vptr)[2]))(ptr); return0; }
最后的结果输出
1 2 3 4
This is Base Function(no virtual), x = 0 This is Derived::vfunc1(virtual), y = 10 This is Base::vfunc2(virtual), x = 0 This is Derived::vfunc3(virtual), y = 10