多态指的是派生类重写基类方法,然后让基类引用指向派生类对象,调用方法时候会进行动态绑定。多态可以分为静态多态和动态多态。
- 静态多态:在编译阶段就已经绑定了函数地址,主要体现是重载、模板。
- 动态多态:利用虚函数实现,在运行期间绑定,主要体现是给父类指针传递不同的类型,调用的函数也会不同。
搭配理解的博文:程序编译的四个过程
目录
1、静态多态
重载的构成条件是在同一作用域内,两个同名函数的形参个数、类型、顺序至少要有一者不同。在编译阶段借助C++符号修饰规则可以得到不同的符号名,然后在链接阶段,不同的符号名会绑定了对应的函数地址。
模板也是在链接阶段才会去实例化。汇编阶段将所有的符号进行汇总,然后在链接阶段实例化,并在符号表中填入对应的函数地址。
2、动态多态
动态多态在运行期间绑定。以下面这段代码为例,TicketWindow 函数的形参 p 一开始不知道指向的是父类Person,还是子类 Student。
class Person {
public:
virtual void BuyTicket() { cout << "Person类:买票-全价" << endl; }
};
class Student : public Person {
public:
// 子类的 virtual 可以不写,但是父类的必须写
virtual void BuyTicket() { cout << "Student类:买票-半价" << endl; }
};
// 售票窗口
void TicketWindow(Person& p)
{
p.BuyTicket();
}
只有执行了 main 函数里的内容才知道,第一次是指向了父类对象,此时就会去父类Person的虚表里找虚函数;第二次是指向了子类对象,此时就会去子类Student的虚表里找虚函数。
int main(){
Person ps;
Student st;
TicketWindow(ps); // 传递Person对象买成人票
TicketWindow(st); // 传递Student对象买半票
}