单继承虚函数表
- 什么是虚函数表?
含有虚函数的类实例化出的对象内存会多出四个字节,前四个字节存储一个指针,叫虚表指针,这个指针指向一张表,这张表按顺序存储了重写的虚函数,叫虚(函数)表。
基类虚表的构建原则
- 将基类虚函数按照其在类中声明的先后顺序依次存放在虚表中。
派生类虚表构建原则
- 只要基类中有虚函数,即使派生类没有重写基类的虚函数,派生类也会有自己的虚表指针,这个指针指向的虚表与基类的虚表内容完全相同,而是对基类虚表的一份拷贝。
class A{
public:
virtual void print1(){
cout<<"A::print()"<< endl;
}
virtual void print2(){
cout << "A::print()" << endl;
}
virtual void print3(){
cout << "A::print()" << endl;
}
int _a;
};
class B:public A{
public:
//派生类B并没有重写基类的虚函数
int _b;
};
int main(){
A a;
B b;
//cout << sizeof(A) << endl;//8 int _a+虚表指针
//cout << sizeof(B) << endl;//12 int _a+int _b+虚表指针
b._a = 1;
b._b = 2;
return 0;
}
- 如果派生类重写了基类的虚函数,编译器将会使用派生类自己的虚函数覆盖表中的相同偏移量位置的基类虚函数。
- 派生类中新增加的虚函数也会存放在虚表中,并按照在类中声明的顺序依次存放在重写的虚函数后面。
class A{
public:
virtual void print1(){
cout<<"A::print1()"<< endl;
}
virtual void print2(){
cout << "A::print2()" << endl;
}
virtual void print3(){
cout << "A::print3()" << endl;
}
int _a;
};
class B:public A{
public:
virtual void print4(){//新增的虚函数
cout << "B::print4()" << endl;
}
virtual void print1(){
cout << "B::print1()" << endl;
}
//A::print2()没有重写
virtual void print3(){
cout << "B::print3()" << endl;
}
virtual void print5(){
cout << "B::print5()" << endl;
}
int _b;
};
int main(){
A a
B b;
b._a = 1;
b._b = 2;
return 0;
}
多继承虚函数表
class A2{
public:
virtual void print3(){
cout << "A2::print3()" << endl;
}
virtual void print4(){
cout << "A2::print4()" << endl;
}
int _a2;
};
class B:public A1,public A2{
public:
virtual void print1(){
cout << "B::print1()" << endl;
}
virtual void print3(){
cout << "B::print3()" << endl;
}
virtual void print5(){
cout << "B::print5()" << endl;
}
int _b;
};
//打印虚表
typedef int(*pVF)();
void printvft(A1& a, string s){
cout << s << endl;
pVF* p = (pVF*)*(int*)&a;
while (*p){
(*p)();
p++;
}
}
void printvft(A2& a, string s){
cout << s << endl;
pVF* p = (pVF*)*(int*)&a;
while (*p){
(*p)();
p++;
}
}
int main(){
B b;
b._a1 = 1;
b._a2 = 2;
b._b = 3;
A1& a1 = b;
A2& a2 = b;
printvft(a1, "B从A1继承下来的虚表:");
printvft(a2, "B从A1继承下来的虚表:");
return 0;
}
菱形继承虚函数表
class A{
public:
virtual void print1(){
cout << "A::print1()" << endl;
}
virtual void print2(){
cout << "A::print2()" << endl;
}
virtual void print3(){
cout << "A::print3()" << endl;
}
int _a;
};
class B1 :public A{
public:
virtual void print1(){
cout << "B1::print1()" << endl;
}
virtual void print4(){
cout << "B1::print4()" << endl;
}
int _b1;
};
class B2 :public A{
public:
virtual void print2(){
cout << "B2::print2()" << endl;
}
virtual void print5(){
cout << "B2::print5()" << endl;
}
int _b2;
};
class C :public B1, public B2{
public:
virtual void print1(){
cout << "C::print1()" << endl;
}
virtual void print2(){
cout << "C::print2()" << endl;
}
virtual void print3(){
cout << "C::print3()" << endl;
}
virtual void print4(){
cout << "C::print4()" << endl;
}
/*virtual void print5(){
cout << "C::print5()" << endl;
}*/
virtual void print6(){
cout << "C::print6()" << endl;
}
int _c;
};
typedef int(*pVF)();
void printvft(B1& b, string s){
cout << s << endl;
pVF* p = (pVF*)*(int*)&b;
while (*p){
(*p)();
p++;
}
}
void printvft(B2& b, string s){
cout << s << endl;
pVF* p = (pVF*)*(int*)&b;
while (*p){
(*p)();
p++;
}
}
int main(){
C c;
c.B1::_a = 1;
c.B2::_a = 2;
c._b1 = 3;
c._b2 = 4;
c._c = 5;
B1& b1 = c;
B2& b2 = c;
printvft(b1, "c从B1继承下来的虚表:");
printvft(b2, "c从B1继承下来的虚表:");
return 0;
}
从上面两张图发现:
- 菱形继承中只要有虚函数,也会一步步实现多态的重写。
菱形虚拟继承暂时还未弄明白,请各位指教。