跳至主要內容

虚函数的访问

张威大约 4 分钟c/c++多态

虚函数的访问

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->虚函数名”的形式来调用,编译器仍将其解释为静态联编的“本类名::虚函数名。即**它们所调用的虚函数是自己类中定义的函数,如果在自己的类中实现该函数,。但绝不会调用任何在派生类中重定义的虚函数。 **

注意

虚函数的调用一定就是动态绑定吗?

在类的构造函数当中,调用虚函数,也是静态绑定。构造函数中调用其他函数,包括虚函数,不会发生动态绑定。

注意:

  1. 用对象本身调用虚函数,是静态绑定。

  2. 动态绑定:

  3. 如果不是通过指针或者引用来调用虚函数,那就是静态绑定。