这是我参与11月更文挑战的第13天,活动详情查看:2021最后一次更文挑战
C++多态
C++的多态被称为三大特性之一,被概括为“一个接口,多种方法”,它是面向对象编程领域的核心概念。事实上,当我看到多态这个概念后,立马发现自己曾在JS和TS代码实践中接触过它,实习中常见基类声明一个方法,但并不具体实现,在不同的子类中,对这个方法进行不同的实现。除了这种思想外,C++中的多态还涉及许多语言层级和编译的细节。
实现多态的两种方式:
- 在子类中重写基类方法(
Override) - 使用
virtual关键字 对于第一种方法要注意的是,重写也即Override是在类实现中重载类成员函数和虚函数(不同的函数参数列表,多个同名函数共存),不是在类声明时重新写这些函数,这样的操作被称为隐藏,即后面的实现覆盖了前面的实现,来个例子:
class Base
{
public:
virtual void f(float x)
{
cout<<"Base::f(float)"<< x <<endl;
}
void g(float x)
{
cout<<"Base::g(float)"<< x <<endl;
}
void h(float x)
{
cout<<"Base::h(float)"<< x <<endl;
}
};
class Derived : public Base
{
public:
virtual void f(float x)
{
cout<<"Derived::f(float)"<< x <<endl; //多态、覆盖
}
void g(int x)
{
cout<<"Derived::g(int)"<< x <<endl; //隐藏
}
void h(float x)
{
cout<<"Derived::h(float)"<< x <<endl; //隐藏
}
};
关于函数隐藏和virtual的关系,更详细的见此文
回到多态上来,上面两种多态的实现分别对应不同的绑定方式:
- 通过重载函数实现:先期联编 static binding
- 通过虚函数实现 :滞后联编 dynamic binding 解释一下函数的绑定何意:如果函数的调用,在编译器编译期间就可以确定函数的调用地址,并生产代码,是静态绑定,也称早绑定的。而如果函数调用的地址不能在编译器期间确定,需要在运行时才确定,这就属于动态(晚)绑定。