先上两个简单的父类子类。
class Base
{
public:
void func()
{
cout << "Base……" << endl;
}
virtual void func1(int value = 1)
{
cout << "Base 虚函数 value =" << value << endl;
}
};
class Derive : public Base
{
public:
void func()
{
cout << "Derive……" << endl;
}
virtual void func1(int value = 2)
{
cout << "Derive 虚函数 value =" << value << endl;
}
};
Main函数下:
Derive derive;
Derive *pdervie = &derive;
pdervie->func();//调用的子类函数
Base *pbase = &derive;
pbase->func();//调用的父类函数
普通函数是静态绑定,调用哪个的类的成员函数取决于静态类型。
就是定义时候的类型,不管他指向了哪个类型,在编译期
结论,不应该在子类中重新定义一个继承来的成员函数。
//虚函数的动态绑定
Base base;
pdervie->func1();//子类调用虚函数
pbase->func1();//父类调用
pbase = &base;//现在重新指向回父类指针类型
pbase->func1();//于是重新调用了父类的虚函数
//Derive 虚函数 value =1
结论虚函数是动态绑定,调用哪个类的虚函数,取决于指向了何种类型
但是,虚函数的缺省参数是静态绑定的,所以value的值还是1,因为编译器实现缺省参数的动态绑定效率比较低,所以做了一个取舍
C++中的多态体现
有一个观点是肯定的:多态,必须是存在虚函数,并且调用虚函数
当我们调用了一个虚函数的时候,走的是不是通过虚函数表来找到虚函数表,然后执行虚函数,如果是这样,必然是多态,否则就不是
特别说明,如果类有多个基类,则有多个虚函数表指针,并不是多个虚函数表,且子类于第一个基类共用,vptr
如果父类有虚函数,就等于子类也有,就等于也有虚函数表指针,同属一个类,共用共享的虚函数表
比如:Base base=derive;
直接用子类对象给父类对象赋值
初始化父类时,把子类属于父类的一部分切割出来,给了子类,但是子类的虚函数表指针值不去覆盖父类的,这是编译器的优化选择。