C++ overload and override

重载(overload)和重写(override)

In C++, overload and override are not related, but they are easily confused due to the similarity of the terms.

On Stack Overflow, there is a related question accompanied by an interesting image:

Now, back to the point — overload:

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

That is: when two or more function names are the same but have different signatures in the same scope, overloading occurs.

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

A function signature includes the name, parameter type list, and enclosing namespace (if any), and does not include return type, so if two functions differ only in their return types, they cannot be overloaded.

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);

On the other hand, 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.

That is: when a derived class function and a base class virtual function have the same signature (class member function signature (also without return type, thus allowing for covariant return)) override occurs.

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);
};

However, when the parameter list differs, a different rule applies:

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.

That is:

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;
}
};

In the code above, B::func(int) overrides A::func(int), while B::func(double) does not override anything; it overloads B::func, noting that it does not overload the base class member A::func because they are in different scopes.

Signatures in C++

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

The keywords override/final in C++ were introduced after C++11 (not present in C++98/03), both are virt-specifier (with final also being a class-virt-specifier), described syntactically as follows:

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

The significance of this feature is to allow developers to explicitly indicate when they wish to override a base class virtual function (override), or when that virtual function should not allow subsequent derived classes to override it (final), preventing ambiguity due to differing signatures:

[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.

The article is finished. If you have any questions, please comment and communicate.

Scan the QR code on WeChat and follow me.

Title:C++ overload and override
Author:LIPENGZHA
Publish Date:2017/02/06 05:08
Word Count:3.4k Words
Link:https://en.imzlp.com/posts/29726/
License: CC BY-NC-SA 4.0
Reprinting of the full article is prohibited.
Your donation will encourage me to keep creating!