“重写(覆盖)、重载、重定义、多态” 绝对称得上是C++里一个比较经典的问题了,下面我们来层层剖析它。
重写(覆盖)override
重写又名覆盖,常见于子类继承父类的时候,子类重写父类的某些方法。
有如下要求:
- 父类中被重写的方法必须是virtual的
- 子类中进行重写操作的那个方法,访问修饰符和父类的可以不同(即根据自身需要选择public、protected、private), 但是返回值、参数列表(参数的顺序、类型)和父类必须相同。
下面是一个重写的例子:
输出为:AAA
重载 overload
重载是指对同一个名称的函数,根据其参数的不同可以执行不同的操作。
举个栗子,下面的几种函数都属于重载,他们的要求就是参数表(参数个数、参数类型、参数顺序)必须至少要有一点不同!
注意啦,重载强调的是参数表要不同,而如果只改变返回值的类型的话则不属于重载,编译时会报错。比如如下的代码则不算是重载:
这个例子中编译会报:error: 'void A::f()' cannot be overloaded
重载还有一个地方需要注意,就是重载很容易产生二义性。
比如:
当你执行f(2)
的时候,编译器不知道你要执行的是哪一个函数,这个时候的调用办法如下:
重载还可以用来重载运算符,这里就不作细致讨论了。
重定义(隐藏) redefining
重定义又称隐藏,它也常见于子类继承父类的情况中,注意区分重定义和重写的区别。
重定义是子类中有一个和父类方法名一样的方法,且父类中那个方法不能被virtual
修饰,而且子类和父类中这个方法的参数表可以不同。
多态 polymorphism
多态是基于重写的,因此基类方法必须加virtual。
我们都知道父类指针可以指向子类对象,而多态就是用于给父类指针调用子类重写后的的方法的。
举个例子就明白了:
总结
- 重写要求基类方法前加上virtual,且返回值及参数列表均需和基类相同。
- 重载要求参数列表和原函数不同,仅有返回值不同不算重载,使用时需要注意二义性。
- 重定义要求方法名和父类相同,其余可以不同,且此时要调用父类方法时只能采用
::
来调用 - 多态是基于重写的一种程序调用方法,当基类的指针指向子类对象时可以调用子类的方法。