C++の関数リロードの実現原理

2799 ワード

1.関数リロードとは?
関数リロードとは、同じ役割ドメイン内で、同じ関数名、異なるパラメータリスト(パラメータ個数、タイプ、順序)を持つ関数のセットを指し、この関数のセットをリロード関数と呼ぶ.リロード関数は通常、機能が似ている関数のセットを宣言するために使用され、関数名の数を減らし、名前空間の汚染を回避し、プログラムの可読性に大きなメリットがあります.
二、なぜ関数でリロードするのか
以前に学習したCでは,1つの機能関数に対して異なるタイプの呼び出しを実現するには,異なる名前を取らなければならない.非常に多く呼び出されると、多くの名前が必要になり、作業量が大幅に増加するため、C++では関数の再ロードを考慮しました.
三、C++関数のリロードはどのように実現しますか?
C++の下部には、次のような名前変更メカニズムがあります.
int型、double型、long型を加算できる加算関数を実現します.C++では、次のことができます.
#include
using namespace std;
int Add(int left, int right)
{
	return left + right;
}

double Add(double left, double right)
{
	return left + right;
}

long Add(long left, long right)
{
	return left + right;
}

int main()
{
	Add(10, 10);
	Add(10.0, 10.0);
	Add(10L, 10L);
	return 0;
}

上記のコードの実装により,特定のAdd()のパラメータに基づいて対応する関数を呼び出すことができる.
下位レベルの名前変更メカニズムでは、Add関数はパラメータの個数、パラメータのタイプ、戻り値のタイプに基づいて再命名されます.では、関数の再ロードを使用すると、1つの関数には複数のネーミングメカニズムがあります. 
C++呼び出し約定(_cdecl呼び出し約定)では、Add関数は下位層で以下のように解析される.
"int __cdecl Add(int,int)"(?Add@@YAHHH@Z)
"double __cdecl Add(double,double)"(?Add@@YANNN@Z)
"long __cdecl Add(long,long)"(?Add@@YAJJJ@Z)
C++プログラムでCコンパイラによってコンパイルされた関数を呼び出すには、なぜextern「C」宣言を追加しますか? 
(1)C++では,関数宣言の前にextern"C"を付けることで,1つの関数をC言語のスタイルでコンパイルすることができる.
(2)C++言語サポート関数リロード.Cは関数のリロードをサポートしません. 
(3)関数CとC++でコンパイルされた関数の名前は異なる.extern"C"を加えると、Cがコンパイルされたことを説明します. 
C++は既にコンパイルされたC関数を呼び出そうとするが,コンパイルされた名前が異なるため,直接呼び出すことはできないため,C++にextern「C」生命を加えてこの問題を解決する. 
例えば、ある関数のプロトタイプをvoid foo(int x,int y);この関数はCコンパイラによってコンパイルされた後のライブラリ内の名前は_foo、C++コンパイラは像_を生成しますfoo_int_intなどの名前にextren"C"を付けると、コンパイラに伝えることになります.関数fooはCコンパイルされた関数で、ライブラリで探すべきは_fooではなくfoo_int_int.
次の2つの関数は関数の再ロードに属しますか?
#include 
using namespace std;
int Add(short left, short right)
{
	return left + right;
}

short Add(short left, short left)
{
	return left + right;
}

この2つの関数は、戻り値が異なるだけで、関数の再ロードを構成しません.
2.関連面接問題
a)C言語はなぜ関数リロードをサポートしないのか
上記の3つのAdd関数は,C++において次のように解析される.
"int __cdecl Add(int,int)"(?Add@@YAHHH@Z)
"double __cdecl Add(double,double)"(?Add@@YANNN@Z)
"long __cdecl Add(long,long)"(?Add@@YAJJJ@Z)
C言語では_Add,3つは同じなので区別できないため,C言語では関数リロードはサポートされていない.
b)C++における関数リロードの下位層はどのように処理されているか
下位レベルの名前変更メカニズムでは、Add関数はパラメータの個数、パラメータのタイプ、戻り値のタイプに基づいて再命名されます.では、関数の再ロードを使用すると、1つの関数には複数のネーミングメカニズムがあります. 
C++呼び出し約定(_cdecl呼び出し約定)では、Add関数は下位層で以下のように解析される.
"int __cdecl Add(int,int)"(?Add@@YAHHH@Z)
"double __cdecl Add(double,double)"(?Add@@YANNN@Z)
"long __cdecl Add(long,long)"(?Add@@YAJJJ@Z)
c)C++の中で1つの関数をCの風格によってコンパイルすることができるかどうか
C++では、関数宣言の前にextern「C」を付けることで、1つの関数をC言語のスタイルでコンパイルできます.