struct IObject {
virtual void MethodA() = 0;
virtual int MethodB(char *) = 0;
};
class A : public IObject {
public:
virtual void MethodA() {
std::cout << "method A" << std::endl;
};
virtual int MethodB(char *p) {
std::cout << "method B " << p << std::endl;
return 0;
};
public:
int MethodC(int c) {
std::cout << "method C non-virtual" << std::endl;
return ++c;
}
private:
int mem_;
};
int main(int argc, cahr *argv[])
{
IObject *pObj = new A;
pObj->MethodA();
pObj->MethodB(NULL);
// FIXME: This is a compile error!
pObj->MethodC(1); // error
delete A;
return 0;
};
C++ 运行时多态, 在执行代码中,主要通过 vtable 实现。让我们用C来重新描述上面的例子。
// VTABLE of class IObject
struct I_IObject {
void *pMethodA(void);
int *pMethodB(char *);
};
// Instance variant type of IObject
struct IObject {
struct I_IObject *vtable_this;
};
// VTABLE of class A
struct A;
struct I_A {
void *pDtor(A*)
};
// Instance object variant type of class A
struct A {
struct I_IObject *vtable_IObject;
struct I_A *vtable_this;
int *pMethodC(int);
int mem_;
};
void A_MethodA (void) {
printf("method A\n");
}
int A_MethodB (char *p) {
printf("method B %s\n", p);
}
int A_MethodC (int c) {
printf("method C non-virtual\n");
return ++c;
}
void A_dtor(struct A *_this) {
free(_this);
}
struct A *A_ctor() {
struct A *p = malloc(sizeof(struct A));
// Non-virtual function will be assign the value directly.
p.pMethodC = &A_MethodC;
/////////////////////////////////////////////////
// vtable initialization code
#ifdef A_MethodA
p.vtable_IObject->pMethodA = &A_MethodA;
#else
p.vtable_IObject->pMethodA = &IObject_MethodA; // Warning!
#endif
#ifdef A_MethodB
p.vtable_IObject->pMethodB = &A_MethodB;
#else
p.vtable_IObject->pMethodB = &IObject_MethodB; // Warning!
#endif
// vtable of A itself
p.vtable_self->pDtor = &A_dtor;
return p;
}
int main(int argc, char *argv[])
{
IObject *pObj = (IObject*) A_ctor();
pObj->vtable_self->pMethodA();
pObj->vtable_self->pMethodB(NULL);
A_dtor(pObj);
return 0;
}
C的定价物确实有些繁琐,不过基本的结构就是这样了。具体说来是这样:
1,如果一个类 virtual function, 这些 virtual funciton 就会被统一在一个 vtable 中;
2,包含 virtual function 的class 都会有一个指向 vtable structure的指针,如果当前类重写了 virtual function, 在对象初始化的时候相应的虚函数指针就会被替换;
3,虚函数的调用一律通过vtable定位,因为存在vtable这一层中继,就可以保证在运行态可以通过父类的指针执行指向子类对象的方法,因为类对象初始化的时候正确的重写了vtable的内容。
4,一个对象多一个包含virtual function的基类,就会在类变量的结构中多引入一个指向父类vtable structure的指针。在类对象初始化的时候,就需要更多的 vtable 初始化代码。:D
多重继承会导致 vtable 膨胀, Microsoft ATL 引入了一个 ATL_NO_VTABLE __declspec(novtable) C++ 扩展。关于这个,下回再说~~~
其实这个例子里面还有一个小问题, 不知道大家能不能看出来啊!
没有评论:
发表评论