Function overloading from several examples

Several commonly used functions

#include <iostream>
 
 void func(int a){
     std::cout << "global func: " << a << std::endl;
 }
 namespace test{
     void func(int a){ 
         std::cout << "namespace test func: " << a << std::endl;
     }   
 };
 
 class Demo {
     public:
     void func(int a){
         i = 1;
         std::cout << "class member func: " << a << std::endl;
     }   
     int i{0};
 };
 
 int main()
 {
     func(1);
     test::func(1);
     Demo d;
     d.func(1);
     return 0;
 }

Function overloading

The whole life cycle of the program is as follows: program writing (source code) - > preprocessing - > compilation (scanning - > lexical analysis - > syntax analysis - > semantic analysis - > source code optimization - > code generation - > object code optimization) - > assembly - > link - > run;
When the compiler compiles the source code to generate the object file, the symbol name corresponds to the corresponding variables and functions. In the early days, the two are the same. For example, the assembly source code contains a function foo. When compiling into the object file, the corresponding symbol name is also foo; The rules of C language are similar. Underline the symbolic names of global variables and functions with "";
For example:

 extern "C" {
 void func(int a){ 
     std::cout << "global func: " << a << std::endl;
 }
 }

The compiled symbols are as follows (readelf -s main | grep func):

Num: Value Size Type Bind Vis Ndx Name
60: 00000000000011e9 74 FUNC GLOBAL DEFAULT 16 func

Because the symbol generation rule of C language is like this, function overloading is not supported. Therefore, as long as the symbols are the same (the same function name and variable name will fail to compile)

Then for C + +, it has the characteristics of class, inheritance, virtual mechanism, overloading, namespace and so on, which makes symbol management (symbol generation rules) more complex. In order to support these features, the Name Decoration or Name Mangling mechanism was invented

See how the symbols of the following functions are:

 int func(int){return 0;};
 float func(float){return 0;};
 class C{
     public:
     int func(int){return 0;};  
     class C2 {
         public:
         int func(int){return 0;};
     };  
 };
 namespace N{
 int func(int){return 0;};
 class C{
     public:
     int func(int){return 0;};  
 };
 };
 int main(){
     func(1);
     func(1.0f);
     C c;
     c.func(1);
     C::C2 c2;
     c2.func(1);
     
     N::func(1);
     N::C c1; 
     c1.func(1);
     
     return 0;
 }

Command:
Compilation: G + + main cpp -o main
View symbol: readelf -s main | grep func

Statistics:

Function signatureModified name (symbolic name)
int func(int)_Z4funci
float func(float)_Z4funcf
int C::func(int)_ZN1C4funcEi
int C::C2::func(int)_ZN1C2C24funcEi
int N::func(int)_ZN1N4funcEi
int N::C::func(int)_ZN1N1C4funcE

The basic rules are as follows:

All symbols in_ Starting with Z, for nested names (in namespaces or classes), followed by "N", and then the names of various namespaces and classes. Each name is preceded by the name string length and ends with E. for functions, its parameter list is immediately followed by "e", and for int types, it is the letter i.

  <type> ::= <builtin-type>
         ::= <qualified-type>
         ::= <function-type>
         ::= <class-enum-type>
         ::= <array-type>
         ::= <pointer-to-member-type>
         ::= <template-param>
         ::= <template-template-param> <template-args>
         ::= <decltype>
         ::= P <type>        # pointer
         ::= R <type>        # l-value reference
         ::= O <type>        # r-value reference (C++11)
         ::= C <type>        # complex pair (C99)
         ::= G <type>        # imaginary (C99)
         ::= <substitution>  # See Compression below

<CV-qualifiers>      ::= [r] [V] [K] 	  # restrict (C99), volatile, const

<builtin-type>   ::= v	# void
				 ::= w	# wchar_t
				 ::= b	# bool
				 ::= c	# char
				 ::= a	# signed char
				 ::= h	# unsigned char
				 ::= s	# short
				 ::= t	# unsigned short
				 ::= i	# int
				 ::= j	# unsigned int
				 ::= l	# long
				 ::= m	# unsigned long
				 ::= x	# long long, __int64
				 ::= y	# unsigned long long, __int64
				 ::= n	# __int128
				 ::= o	# unsigned __int128
				 ::= f	# float
				 ::= d	# double
				 ::= e	# long double, __float80
				 ::= g	# __float128
				 ::= z	# ellipsis
                 ::= Dd # IEEE 754r decimal floating point (64 bits)
                 ::= De # IEEE 754r decimal floating point (128 bits)
                 ::= Df # IEEE 754r decimal floating point (32 bits)
                 ::= Dh # IEEE 754r half-precision floating point (16 bits)
                 ::= DF <number> _ # ISO/IEC TS 18661 binary floating point type _FloatN (N bits)
                 ::= DB <number> _        # C23 signed _BitInt(N)
                 ::= DB <instantiation-dependent expression> _ # C23 signed _BitInt(N)
                 ::= DU <number> _        # C23 unsigned _BitInt(N)
                 ::= DU <instantiation-dependent expression> _ # C23 unsigned _BitInt(N)
                 ::= Di # char32_t
                 ::= Ds # char16_t
                 ::= Du # char8_t
                 ::= Da # auto
                 ::= Dc # decltype(auto)
                 ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
				 ::= u <source-name> [<template-args>] # vendor extended type

Whether the name modification of the function contains the return value, there are The following explanation:
Whether the mangling of a function type includes the return type depends on the context and the nature of the function. The rules for deciding whether the return type is included are:

  1. Template functions (names or types) have return types encoded, with the exceptions listed below.
  2. Function types not appearing as part of a function name mangling, e.g. parameters, pointer types, etc., have return type encoded, with the exceptions listed below.
  3. Non-template function names do not have return types encoded.

The exceptions mentioned in (1) and (2) above, for which the return type is never included, are

  1. Constructors.
  2. Destructors.
  3. Conversion operator functions, e.g. operator int.

const overload

Let's look at the following examples:
1:

 void func(int a){ 
     std::cout << "global func: " << a << std::endl;
 }
 void func(const int a){
     std::cout << "global func: " << a << std::endl;
 }

And 2:

 void func(int& a){ 
     std::cout << "global func: " << a << std::endl;
 }
 void func(const int& a){ 
     std::cout << "global func: " << a << std::endl;
 }

First guess how the above two examples behave?
Conclusion: the compilation of example 1 failed, and the compilation of example 2 succeeded; Why?
Backward extrapolation from compiled symbols:

Function prototypeSymbol
void func(int)_Z4funci
void func(const int)_Z4funci
void func(int&)_Z4funcRi
void func(const int&)_Z4funcRKi

Since the symbols generated by void func(int) and void func(const int) are the same, the compilation will inevitably fail; The idea is that when the function parameter is the basic value, the actual parameter is copied and then passed into the function, so whether const or not will not affect the caller, so there is no need to distinguish between the two cases (compiler rules).

Take another example:

 class Demo {
     public:
     void func(int a){ 
         i = 1;
         std::cout << "class member func: " << a << std::endl;
     }   
     void func(int a) const {
     	 // i = 1; // compile fail 
         std::cout << "class member const func: " << a << std::endl;
     }   
     int i{0};
 };

Compile ok;

Function prototypeSymbol
void const Demo::func(int)_ZNK4Demo4funcEi
void Demo::func(int)_ZN4Demo4funcEi

const of the second member function modifies Demo object.

When const modifies the return value, because "non template function names do not have return types encoded"; In this case, the symbols generated by the return value with and without const decoration are the same. If they exist at the same time, the compilation will fail.

Keywords: C++ function

Added by RottenBananas on Sun, 06 Feb 2022 21:44:49 +0200