摘要
问题: 让一个基类指针指向派生类时,对于同名的成员函数,调用的是基类的还是派生类的?
答案: 这取决于基类成员函数是否是virtual
的。
如果基类成员函数是virtual
的,则成员函数为运行期绑定,即调用的是派生类成员函数。
如果基类成员函数不是virtual
的,成员函数为编译期绑定,即调用的是基类成员函数。
其实,
类成员函数不是虚函数,根据指针类型来判断调用基类的函数还是派生类的函数,指针类型是什么就调用对应类的函数。
类成员函数是虚函数,根据指针所指向对象的类型来判断,例如所指向派生类,就调用派生类函数。
涉及知识点:C++覆盖(override)
C++的函数多态是通过虚函数来实现的,则调用某个同名函数时,
疑惑
让一个基类指针指向派生类时,对于同名的成员函数,调用的是基类的还是派生类的?
实验代码和结果
实验代码:
#include<iostream>
using namespace std;
class base
{
public:
virtual void vir1() { printf("base vir1()\n"); }
void vir2() { printf("base vir2()\n"); }
};
class derived : public base
{
public:
void vir1() { printf("derived vir1()\n"); }
void vir2() { printf("derived vir2()\n"); }
};
int main()
{
base *p1 = new base;
base *p2 = new derived;
//derived *p3 = new base; //报错
derived *p4 = new derived;
printf("p1:\n");
p1->vir1();
p1->vir2();
printf("p2:\n");
p2->vir1();
p2->vir2();
printf("p4:\n");
p4->vir1();
p4->vir2();
delete p1;
delete p2;
delete p4;
return 0;
}
运行结果:
p1:
base vir1()
base vir2()
p2:
derived vir1()
base vir2()
p4:
derived vir1()
derived vir2()
请按任意键继续. . .
结论:
注意看这里
p2:
derived vir1()
base vir2()
可以推断出,
如果基类成员函数是virtual
的,则成员函数为运行期绑定,即调用的是派生类成员函数。
如果基类成员函数不是virtual
的,成员函数为编译期绑定,即调用的是基类成员函数。
涉及知识点
覆盖(override)*
覆盖构成条件和多态构成条件是相同的,覆盖是一种函数间的表现关系,而多态描述的是函数的一种性质,二者所描述的其实是同一种语法现象。
覆盖首先要求有继承关系,其次是要求构成继承关系的两个类中必须具有相同函数签名的成员函数,
并且这两个成员函数必须是虚成员函数,具备这两个条件后,派生类中的虚成员函数则会覆盖基类中的同名的虚成员函数。参考这里