虚函数的访问
大约 4 分钟
虚函数的访问
class Base
{
public:
Base(int data = 0):ma(data){}
virtual void show()
{
cout << "Base::show()" << endl;
}
protected:
int ma;
};
class Derive : public Base
{
public:
Derive(int data = 0):Base(data), mb(data){}
void show()
{
cout << "Derive::show()" << endl;
}
private:
int mb;
};
指针访问
使用指针访问非虚函数时,编译器根据决定要调用哪个函数,而不是根据指针指向的对象类型;
使用指针访问虚函数时,编译器根据决定要调用哪个函数(动态联编),而与指针本身的类型无关。
Base b; Derive d; Base *pb1 = &b;//基类指针指向基类对象 pb1->show();
Base b; Derive d; Base *pb2 = &d;//基类指针指向派生类对象 pb2->show();
//派生类指针调用派生类对象,派生类引用调用派生类对象 Derive *pd1 = &d; pd1->show(); Derive &rd1 = d; rd1.show();
向下强转(不安全)

指针指向的是虚函数,属于动态绑定,但是此时派生类的虚函数表里只有基类的虚函数地址,所以最终访问到是基类的虚函数
引用访问
使用引用访问虚函数,与使用指针访问虚函数类似,表现出动态多态特性。不同的是,引用一经声明后,。因此在使用上有一定限制,但这在一定程度上提高了代码的安全性,特别体现在函数参数传递等场合中,可以将引用理解成一种“受限制的指针”。
Base &rb1 = b;
rb1.show();
Base &rb2 = d;
rb2.show();
对象访问
和普通函数一样,虚函数一样可以通过对象名来调用,此时编译器采用的是。通过对象名访问虚函数时, 调用哪个类的函数取决于定义对象名的类型。对象类型是基类时,就调用基类的函数;对象类型是子类时,就调用子类的函数。
Base b;
Derive d;
//静态绑定
b.show();//虚函数 call Base::show();
d.show();//虚函数 call Derive::show();

成员函数中访问
在类内的成员函数中访问该类层次中的虚函数,采用动态联编,要使用this指针。
构造函数和析构函数中访问
构造函数和析构函数是特殊的成员函数,在其中访问虚函数时,C++采用,即在构造函数或析构函数内,即使是使用“this->虚函数名
”的形式来调用,编译器仍将其解释为静态联编的“本类名::虚函数名
”。即**它们所调用的虚函数是自己类中定义的函数,如果在自己的类中实现该函数,。但绝不会调用任何在派生类中重定义的虚函数。 **
注意
虚函数的调用一定就是动态绑定吗?
在类的构造函数当中,调用虚函数,也是静态绑定。构造函数中调用其他函数,包括虚函数,不会发生动态绑定。
注意:
用对象本身调用虚函数,是静态绑定。
动态绑定:
如果不是通过指针或者引用来调用虚函数,那就是静态绑定。