C++中虚函数的主要作用就是实现多态
虚函数表是通过一块连续内存来存储虚函数的地址
在有虚函数的对象实例中都存在一张虚函数表,指明了实际调用的虚函数
实例化出的对象的头上四个字节存放虚表指针
若派生类B继承基类A,则B先开一块空间,将A的虚表拷贝下来,用B的虚表覆盖
虚表存在于常量区,不可能在栈上.若局部变量,栈会随着函数的释放而销毁,出现野指针
虚表中存放虚函数指针数组,以0结尾
单继承对象模型
//此代码用于32位平台
class Base
{
public:
virtual void func1()
{
cout << "Base::func1()" << endl;
}
virtual void func2()
{
cout << "Base::func2()" << endl;
}
private:
int _b;
};
class Derive :public Base
{
public:
virtual void func1()
{
cout << "Derive::func1()" << endl;
}
virtual void func3()
{
cout << "Derive::func3()" << endl;
}
void func4()
{
cout << "Derive::func4()" << endl;
}
private:
int _d;
};
typedef void (*FUNC)();
void PrintVTable(int* table)
{
cout << "虚表地址:" << table << endl;
for (int i = 0; table[i] != 0; ++i)
{
printf("第%d个虚函数地址:0X%x->", i, table[i]);
FUNC f = (FUNC)table[i];
f();
}
cout << endl;
}
void Test()
{
Base b;
Derive d;
int* table_b = (int*)(*(int*)&b);
int* table_d = (int*)(*(int*)&d);
PrintVTable(table_b);
PrintVTable(table_d);
}
int main()
{
Test();
system("pause");
return 0;
}
若要在32位和64位平台下均可运行,则将int*转换成int**
解引用取int*个字节,int*为指针,即为4个字节,也可以转换为char**...
多继承对象模型
class Base1
{
public:
virtual void func1()
{
cout << "Base1::func1()" << endl;
}
virtual void func2()
{
cout << "Base1::func2()" << endl;
}
private:
int _b1;
};
class Base2
{
public:
virtual void func1()
{
cout << "Base2::func1()" << endl;
}
virtual void func2()
{
cout << "Base2::func2()" << endl;
}
private:
int _b2;
};
class Derive :public Base1, public Base2
{
public:
virtual void func1()
{
cout << "Derive::func1()" << endl;
}
virtual void func3()
{
cout << "Derive::func3()" << endl;
}
private:
int _d;
};
typedef void (*FUNC)();
void PrintVTable(int* table)
{
cout << "虚表地址:" << table << endl;
for (int i = 0; table[i] != 0; ++i)
{
printf("第%d个虚函数地址:0X%x->", i, table[i]);
FUNC f = (FUNC)table[i];
f();
}
cout << endl;
}
void Test() {
Derive d;
cout << sizeof(d) << endl;//20
int* table = (int*)(*(int*)&d);
PrintVTable(table);
table = (int *)(*((int*)((char*)&d + sizeof(Base1))));
PrintVTable(table);
}
int main()
{
Test();
system("pause");
return 0;
}
Derive重写每个父类的func1()
自己独有的虚函数存放于先继承的父类的虚表中
*调用所有的虚函数都要到虚表中查找吗?
不是,构成多态的虚函数才要到虚表中查找(指针或引用)
菱形继承对象模型
class A
{
public:
virtual void func1()
{
cout << "A::func1()" << endl;
}
protected:
int _a;
};
class B :public A
{
public:
virtual void func1()
{
cout << "B::func1()" << endl;
}
protected:
int _b;
};
class C :public A
{
public:
virtual void func1()
{
cout << "C::func1()" << endl;
}
protected:
int _c;
};
class D :public B, public C
{
public:
virtual void func1()
{
cout << "D::func1()" << endl;
}
protected:
int _d;
};
typedef void (*FUNC)();
void PrintVTable(int* table)
{
cout << "虚表地址:" << table << endl;
for (int i = 0; table[i] != 0; ++i)
{
printf("第%d个虚函数地址:0X%x->", i, table[i]);
FUNC f = (FUNC)table[i];
f();
}
cout << endl;
}
int main()
{
D d;
cout << sizeof(d) << endl;//28
PrintVTable((int*)(*(int*)&d));
PrintVTable((int*)(*(int*)((char*)&d + sizeof(B))));
system("pause");
return 0;
}
菱形虚继承对象模型
class A
{
public:
virtual void func1()
{
cout << "A::func1()" << endl;
}
int _a;
};
class B :virtual public A
{
public:
virtual void func1()
{
cout << "B::func1()" << endl;
}
int _b;
};
class C :virtual public A
{
public:
virtual void func1()
{
cout << "C::func1()" << endl;
}
int _c;
};
class D :public B, public C
{
public:
virtual void func1()
{
cout << "D::func1()" << endl;
}
virtual void func2()
{
cout << "D::func2()" << endl;
}
int _d;
};
int main()
{
D d;
d._a = 1;
d._b = 2;
d._c = 3;
d._d = 4;
cout << sizeof(d) << endl;//32
system("pause");
return 0;
}
若不在D中重写func1(),则代码无法编译通过.因为编译器不清楚A中的虚表是B的重写还是C的重写
若在D中增加自己的虚函数func2(),则虚函数写入先继承的父类B中,B中虚基表指针前面添加一个虚表指针,虚基表的第一行填入
虚基表到虚表的距离,即-4
若在B,C中增加虚函数func3(),则sizeof(D)=36
多态
静态多态: 重载,在编译期决议确定
静态联编对函数的选择是基于指向对象的指针或者引用的类型,通过对象指针进行的普通成员函数的调用,仅仅与指针的类型有
关,而与此刻指针正指向什么对象无关
动态多态: 通过继承重写基类的虚函数实现的多态,,在运行时决议确定
动态联编只能通过指向基类的指针或基类对象的引用来调用虚函数
class Base
{
public:
virtual void func1()
{
cout << "Base::func1()" << endl;
}
virtual void func2()
{
cout << "Base::func2()" << endl;
}
void display()
{
cout << "Base::display()" << endl;
}
void display(int i)
{
cout << "Base::display(int i)->" << i << endl;
cout << endl;
}
private:
int _a;
};
class Derive :public Base
{
public:
virtual void func1()
{
cout << "Derive::func1()" << endl;
}
void display()
{
cout << "Derive::display()" << endl;
}
void display(int i)
{
cout << "Derive::display(int i)->" << i << endl;
cout << endl;
}
private:
int _b;
};
void Func(Base& b)
{
b.func1();
b.func2();
b.display();
b.display(10);
}
void Test()
{
Base b;
Derive d;
Func(b);
Func(d);
}
int main()
{
Base* p = NULL;
//p->func1();//动态联编 可以编过,崩溃
//p->display();//静态联编 不崩溃
Test();
system("pause");
return 0;
}