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 | void func(int); |
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 | void 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
, andref-qualifier
(or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and itoverrides
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 | struct A{ |
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 | struct A{ |
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), andenclosing 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
, andtemplate 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), andref-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
, andtemplate 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 | virt-specifier-seq: |
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.