虚函数的三种调用方式——对象名、指针和引用

2025-05-22 14:16:09

直接看示例代码

#include

using namespace std;

class Father

{

public:

Father(){};

virtual void func()

{

cout<<"Father"<

}

void func2()

{ cout<<"Father_func2"<

};

class Child:public Father

{

public:

Child(){};

virtual void func()

{

cout<<"Child"<

}

void func2()

{ cout<<"Child_func2"<

};

int main()

{

Father f;

Child c;

f=c;

f.func2();//只能调用基类中函数,输出“Father_func2”

f.func();//通过对象名调用,输出“Father”

Father &fa=c;

fa.func();//通过引用调用,输出“Child”

Father *fat=&c;

fat->func();//通过指针调用,输出“Child”

return 0;

}

可以得出如下结论:

通过子类赋值给父类,然后调用虚函数,不会引发动态绑定。通过子类赋值给父类,然后调用成员函数(无论是否为虚函数),如示例中f.func2()的方式,只能调用派生类中的基类成员,而不能访问派生类增加的成员(同名函数按基类和派生类区分开);通过指针和引用调用虚函数,可以实现运行时多态,具体实现涉及虚函数指针vptr和虚函数表vtbl相关知识。通过对象名调用虚函数,在编译阶段就能确定调用的是哪一个类的虚函数,所以属于静态关联,如果通过基类指针调用虚函数,在编译阶段无法从语句本身确定调用哪一个类的虚函数,只有在运行时,指针指向某一具体对象后,才能确定调用的是哪一个类的虚函数,故为动态关联;

tips:

动态联编是指在程序运行的时候,编译器才去判断调用哪个函数或如何执行程序。如if-else结构、switch结构等。静态联编是指程序在编译阶段就确定了如何执行。