重载(overload)和重写(override)

C++中重载(overload)重写(override)并无关系,但是由于这个词比较相似还是容易搞混的。

Stack overflow上相关问题下有人配的一个趣图:

下面言归正传——重载(overload)

When two or more different declarations are specified for a single name in the same scope, that name is said to be overloaded.

既:当同一个作用域内的两个或者更多个函数名字相同但签名(signature)不同时,就会发生重载。

1
2
void func(int);
void func(float);

function signature包含了name, parameter type list, and enclosing namespace (if any),没有return type,所以,如果两个函数只有返回类型不同时,不能够重载。

Function declarations that differ only in the return type cannot be overloaded.

1
2
3
void func(int);
// error: functions that differ only in their return type cannot be overloaded
int func(int);

重写(override)

If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list (8.3.5), cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides Base::vf. For convenience we say that any virtual function overrides itself.

即:当派生类函数和基类虚函数具有相同的签名(class member function signature(同样没有return type,所以可以实现协变返回covariant return))时,就会发生重写(override)

1
2
3
4
5
6
7
struct A{
virtual void func(int);
};
struct B:public A{
// override A::func(int) to B::func(float)
virtual void func(float);
};

但是当参数列表不相同时,就应用到了另一种规则:

A function with the same name but a different parameter list (Clause 13) as a virtual function is not necessarily virtual and does not override. The use of the virtual specifier in the declaration of an overriding function is legal but redundant (has empty semantics). Access control (Clause 11) is not considered in determining overriding.

即:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct A{
virtual void func(int){
cout<<"A::func(int)"<<endl;
}
};
struct B:public A{
// Overrides A::func
virtual void func(int){
cout<<"B::func(int)"<<endl;
}
// Does not override A::func (due to different parameter-type-list)
virtual void func(double){
cout<<"B::func(double)"<<endl;
}
};

上面代码中的B::func(int)重写(override)了A::func(int),而B::func(double)没有重写任何东西,它重载(overload)了B::func,注意它并不重载基类成员A::func,因为他们位于不同的作用域。

C++中的签名(signature)

function

<function> name, parameter type list (8.3.5), and enclosing namespace (if any)
[ Note: Signatures are used as a basis for name mangling and linking. — end note ]

function template

<function template> name, parameter type list (8.3.5), enclosing namespace (if any), return type, and template parameter list

function template specialization

<function template specialization> signature of the template of which it is a specialization and its template arguments (whether explicitly specified or deduced)

class member function

<class member function> name, parameter type list (8.3.5), class of which the function is a member, cv-qualifiers (if any), and ref-qualifier (if any)

class member function template

<class member function template> name, parameter type list (8.3.5), class of which the function is a member,cv-qualifiers (if any), ref-qualifier (if any), return type, and template parameter list

class member function template specialization

<class member function template specialization> signature of the member function template of which it is a specialization and its template arguments (whether explicitly specified or deduced)

override/final

C++中的关键字ovrride/final是自C++11之后新增的(C++98/03都没有),均是virt-specifierfinal也是class-virt-sprcifier),语法描述如下:

1
2
3
4
5
6
7
8
virt-specifier-seq:
virt-specifier
virt-specifier-seq virt-specifier
virt-specifier:
override
final
pure-specifier:
= 0

这个特性诞生的意义在于解决我要明确地表示要覆写(override)基类的虚函数(override),或者该虚函数不允许后续的派生类再覆写(final),防止因为签名的不同造成理解上的歧义:

[ISO/IEC 14882:2011]A function with the same name but a different parameter list (Clause 13) as a virtual function is not necessarily virtual and does not override.

全文完,若有不足之处请评论指正。

微信扫描二维码,关注我的公众号。

本文标题:重载(overload)和重写(override)
文章作者:查利鹏
发布时间:2017年02月06日 05时08分
本文字数:本文一共有2.7k字
原始链接:https://imzlp.com/posts/29726/
许可协议: CC BY-NC-SA 4.0
文章禁止全文转载,摘要转发请保留原文链接及作者信息,谢谢!
您的捐赠将鼓励我继续创作!