[C++ 初級] C++ 入門 - デフォルト パラメーター、関数のオーバーロード

ここに画像の説明を挿入

1. デフォルトパラメータ

1.1 定義

 デフォルトパラメータは、関数の宣言または定義時に関数のパラメータのデフォルト値を指定します関数を呼び出すとき、実パラメータが指定されていない場合は仮パラメータのデフォルト値が採用され、それ以外の場合は指定された実パラメータが使用されます。

//缺省参数
void fun(int a = 10)
{
    
    
	cout << a << endl;
}

int main()
{
    
    
	fun(2);//传参了,使用显式传递的值
	fun();//没有传参,使用缺省参数
}

ここに画像の説明を挿入
fun上記のコードでは、関数の仮パラメータ部分  にデフォルト値 10 が指定されています。これfunは、関数の呼び出し時にパラメータを渡すことができるかどうかを意味します。パラメータが渡された場合、仮パラメータはa明示的に渡された値を使用します。パラメータを渡すときは、a仮パラメータのデフォルト値 10 を使用します。

1.2 デフォルトパラメータの分類

  • すべてのデフォルトパラメータ
void text(int a = 5, int b = 15, int c = 25)//全缺省,所有参数都给了缺省值
{
    
    
	cout << a << ' ';
	cout << b << ' ';
	cout << c << ' ';
	cout << endl;
}

int main()
{
    
    
	text(1, 2, 3);
	text(1, 2);
	text(1);
	text();
	return 0;
}

ここに画像の説明を挿入
 すべてのデフォルト パラメータについて、パラメータを渡すとき、パラメータは左から右の順序でデフォルト設定されデフォルトをスキップすることはできません。つまり、最初の仮パラメータと 3 番目の仮パラメータには明示的に値を渡しますが、2 番目のパラメータには値を渡します。デフォルト値を使用してください。この方法は許可されていません。上記のコードは例です: パラメーターが渡されない場合、すべての仮パラメーターはデフォルト値を使用します。パラメーターが 1 つだけ渡された場合、このパラメーターは最初の仮パラメーターに割り当てられ、後の 2 つの仮パラメーターはデフォルト値を使用します。 2 つのパラメータを渡す場合、最初の実パラメータは最初の仮パラメータに割り当てられ、2 番目の実パラメータは 2 番目の仮パラメータに割り当てられ、最後の仮パラメータはデフォルト値を使用します。3 つのパラメータを渡す場合、すべて仮パラメータが使用されます。パラメータは実際のパラメータによって渡される値です。ここでパラメータのプッシュと区別する必要があり、スタック フレームへのパラメータのプッシュの順序は右から左になります。

  • 準デフォルトパラメータ
void text(int a, int b = 15, int c = 25)//半缺省,只有部分参数给了缺省值
{
    
    
	cout << a << ' ';
	cout << b << ' ';
	cout << c << ' ';
	cout << endl;
}

int main()
{
    
    
	text(1, 2, 3);
	text(1, 2);
	text(1);
	return 0;
}

注:
 準デフォルト パラメータには、右から左にデフォルト値を与える必要があります。つまり、最初の仮パラメータと 2 番目の仮パラメータにはデフォルト値が与えられますが、3 番目の仮パラメータにはデフォルト値が与えられません。この種のパラメータは、状況は許されません。また、分離することもできず、つまり、3 番目の仮パラメータと最初の仮パラメータにはデフォルト値が与えられるが、2 番目の仮パラメータにはデフォルト値が与えられないという状況も許可されません。

1.3 デフォルトパラメータは関数宣言内でのみ使用できます

 不一致を避けるために、デフォルト パラメータは関数の宣言と定義に同時に出現することはできず、関数の宣言にのみ出現することが必要です。なぜそれを関数の定義に含めることができないのでしょうか?
 ヘッダファイルは前処理の段階で展開されるため、一般的な関数宣言はヘッダファイル内に配置されます。関数の定義内でのみデフォルト値が指定されている場合、ヘッダファイル展開後、関数の宣言文にデフォルトのパラメータが存在しません。このとき、関数呼び出し時にパラメータが渡されず、デフォルト値を使用したい場合、プログラムのコンパイルのプロセスで問題が発生します。つまり、関数の宣言にデフォルト値が指定されていないため、パラメータを明示的に渡す必要がありますが、呼び出し時にパラメータが渡されません。関数。

2. 関数のオーバーロード

 自然言語では、単語は複数の意味を持つことができ、人は文脈を通じて単語の本当の意味を判断できます。つまり、単語が多重定義されています。例: 私たちの国には、見る必要も心配する必要もないスポーツが 2 つあると言う人もいます。一つは卓球、もう一つは男子サッカーです。前者は「誰も勝てない!」、後者は「誰も勝てない!」という意味ですが、前者は誰も勝てない、後者は他人に勝てないという意味であることは誰もが理解しています。

2.1 定義

 関数のオーバーロードは関数の特殊なケースです。C++ では、同様の関数を持つ同じ名前の複数の関数を同じスコープ内で宣言できます。

2.2 過負荷を構成するいくつかの状況

  • パラメータのタイプは異なります。
int Add(int left, int right)
{
    
    
	cout << "int Add(int left, int right)" << endl;
	return left + right;
}
double Add(double left, double right)
{
    
    
	cout << "double Add(double left, double right)" << endl;
	return left + right;
}
int main()
{
    
    
	cout << Add(1, 2) << endl;
	cout << Add(1.0, 2.0) << endl;
}

ここに画像の説明を挿入
 上記のコードはAdd、同じ名前の 2 つの関数を定義していますが、パラメータの型が異なります。最初の 2 つのパラメータは両方の型でint、次の 2 つのパラメータはdouble両方の型です。Add関数を呼び出すと、コンパイラは実際のパラメータの型を自動的に決定します。どの関数を呼び出すかを決定します。なぜコンパイラがこのようなことができるのかについては、後ほど説明します。

  • パラメータの数が異なります。
void fun()
{
    
    
	cout << "f()" << endl;
}
void fun(int a)
{
    
    
 cout << "f(int a)" << endl;
}
int main()
{
    
    
	fun();
	fun(1);
	return 0;
}

ここに画像の説明を挿入

  • パラメータの型の順序が異なります。
// 3、参数类型顺序不同
void Text(int a, char b)
{
    
    
	cout << "Text(int a,char b)" << endl;
}
void Text(char b, int a)
{
    
    
	cout << "Text(char b, int a)" << endl;
}

int main()
{
    
    
	Text(1, 'a');
	Text('a', 1);
	return 0;
}
  • デフォルトパラメータの場合
void fun()
{
    
    
	cout << "f()" << endl;
}
void fun(int a = 10)
{
    
    
 cout << "f(int a)" << endl;
}
int main()
{
    
    
	//fun();//无参调用会出现歧义
	fun(1);//调用的是第二个
	return 0;
}

 関数オーバーロードの定義によれば、上記のコード内の 2 つの関数はfun関数オーバーロードを構成し、最初の関数にはパラメーターがなく、2 番目の関数には上記のパラメーターの数に属する整数パラメーターがあるため、コンパイルは成功します。 . 状態。しかし、funこの関数には問題があります。どちらのfun関数もパラメータを渡すことができないため、パラメータなしで呼び出すとあいまいさが生じます。
注:
 戻り値の型は、関数がオーバーロードを構成するかどうかとは関係ありません。つまり、同じ関数名、同じ仮パラメータ リストの形状、および異なる戻り値は、関数のオーバーロードを構成しません。
ここに画像の説明を挿入

2.3 C++ は関数のオーバーロードの原則をサポートしています

 上で述べたように、コンパイラはパラメータの型に応じてどの関数を呼び出す必要があるかを自動的に決定します。では、コンパイラはどのようにそれを行うのでしょうか? この質問に答えるには、コンパイルとリンクに関するある程度の知識が必要になります。忘れてしまった学生は、私の以前の記事「 [C 言語上級] コンパイルとリンク」を読んでください実際、ここには関数シグネチャ
の概念  が関係しており、関数シグネチャには、関数名、そのパラメータの型、そのクラスと名前空間、その他の情報を含む関数に関する情報が含まれています関数シグネチャは、シグネチャがさまざまな人物を識別するために使用されるのと同じように、さまざまな関数を識別するために使用され、関数の名前は関数シグネチャの一部にすぎません。同じ関数名で異なるパラメーター リストを持つ関数の場合、コンパイラーとリンカーはシンボルを処理するときに、特定の名前変更方法 (コンパイラーが異なれば異なります) を使用するため、各関数シグネチャは変更された nameに対応します。アセンブリ プロセス中に、コンパイラは関数と変数の名前を変更してシンボリック名を形成します。つまり、C++ ソース コードのコンパイル後にターゲット ファイルで使用されるシンボリック名は、対応する関数と変数の変更された名前になります。C++ コンパイラとリンカは両方とも、関数と変数を識別して処理するためにシンボルを使用するため、関数シグネチャが異なる関数については、関数名が同じであっても、コンパイラとリンカは両方とも異なる関数であると認識します。  Windows での変更ルールは複雑すぎるのに対し、Linux での g++ の変更ルールはシンプルでわかりやすいため、以下では g++ を使用して変更された名前を示します。次のコードを例として取り上げます。

#include <stdio.h>                                                                                                                                                                                            
int Add(int left, int right)
{
    
    
	printf("int Add(int left, int right)\n");
	return left + right;
}

double Add(double left, double right)
{
    
    
	printf("double Add(double left, double right)\n");
	return left + right;
}
int main()
{
    
    
	Add(1,2);
	Add(1.0,2.0);
	return 0;
}

 まずg++ text.cpp -o text.outこの命令を使用して上記のコードをコンパイルし、実行可能プログラム tetx.out を生成します。次に、objdump -S text.outこの命令を使用して変更された名前を表示します。
ここに画像の説明を挿入
 その中には_Z固定プレフィックスがあり、3関数名の長さを示し、Add関数名です。これはiint の省略形であり、2 つの i は両方のパラメータが int 型であることを意味し、dそれは double の省略形であり、2 です。 d は、両方のパラメータが double 型であることを意味します。C++ は関数の変更ルールによって区別されており、パラメータが異なれば変更名も異なり、オーバーロードもサポートされます。分析の結果、変更された名前には関数の戻り値に関連する情報が含まれていないことがわかり、上記の戻り値の型は関数がオーバーロードを構成するかどうかに関係がないことも検証されます。 。
 C言語コンパイラgccの処理結果を見ると、
ここに画像の説明を挿入
 gccコンパイル後も関数名の変更は変わっていないことがわかります。同じ名前の関数を区別する方法がないため、C 言語が関数のオーバーロードをサポートしていないのはこのためです。


 今日のシェアはここまでです!記事が悪くないと思ったら、3回連続で応援していただければ、中連が前進する原動力となります!
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/weixin_63115236/article/details/131468717