目次
3. 名前空間のメンバーを使用するにはどうすればよいですか?
3. C++ では関数のオーバーロードがサポートされているのに、C ではサポートされていないのはなぜですか?
1: 名前空間
1. 名前空間の意味
① 大規模なプロジェクトでは、多くの関数、クラス、変数などが存在することがよくあります。制限しないと、異なる関数やクラスが同じ名前を使用する可能性があり、競合が発生します。② この問題を解決するために、C++ では名前空間の概念を導入しています。これにより、競合を避けるために、関連する関数、クラス、変数などを同じ名前空間の下に置くことができます。③ 同時に、名前空間によりプログラムの可読性や保守性も向上するため、デバッグ時などの問題点の発見に便利です。
2. 名前空間の定義
名前空間を定義するには、名前空間キーワード、その後に名前空間の名前、そして名前空間のメンバーである {} のペアを使用する必要があります。コード:
//命名空间 namespace stu { //命名空间中可以定义变量/函数/类型 int Add(int x, int y) { return x + y; } int goal = 50; struct Node { int data; struct Node* next; }; //命名空间可以嵌套定义 namespace teacher { //命名空间中可以定义变量/函数/类型 int Add(int x, int y) { return x + y; } int goal = 100; struct Node { int data; struct Node* next; }; } }
注: ネームスペースは新しいスコープを定義し、ネームスペース内のすべてのコンテンツはそのネームスペースに制限されます。
3. 名前空間のメンバーを使用するにはどうすればよいですか?
①名前空間名とスコープ修飾子の追加コード:
#include <stdio.h> //命名空间 namespace stu { //命名空间中可以定义变量/函数/类型 int Add(int x, int y) { return x + y; } int goal = 50; struct Node { int data; struct Node* next; }; //命名空间可以嵌套定义 namespace teacher { //命名空间中可以定义变量/函数/类型 int Add(int x, int y) { return x + y; } int goal = 100; struct Node { int data; struct Node* next; }; } } int main() { printf("%d\n", stu::goal); printf("%d\n",stu::teacher::goal); }
②名前空間でメンバーを紹介する場合はusingを使用します
コード:
using stu::goal; //如果想使用嵌套空间中的goal,可以用using stu::teacher::goal //但是两个不能同时存在,否则会导致多次声明 int main() { printf("%d\n",goal); }
③使用している名前空間の名前空間名を使用してインポート(すべての名前空間を展開するのと同等)
コード:
using namespace stu; //想访问嵌套空间的goal,可以using namespace stu::teacher //但是两个不能同时存在,否则goal不明确 int main() { printf("%d\n",goal); }
まとめ
① C++ の一部の重要な宣言や定義(出力に関係する cout など)も名前空間に配置されており、名前空間を拡張したりメンバを導入したりすることなく、変数名や関数名として cout を使用できます。
②より大きなプロジェクトを書きたい場合は、名前空間のメンバーを使用する上記の3つの方法名前空間を直接導入(拡張)するのは非常に良くなく、名前の衝突を引き起こしやすい(名前空間ネームスペースを使用)頻繁に使用する必要がない場合は、名前空間名とスコープ修飾子を追加して使用できます。
(名前空間::メンバー)
特定のメンバーのみを頻繁に使用する必要がある場合は、using を使用して名前空間に単一のメンバーを導入できます
(namespace::member を使用)。
③同じ名前の名前空間が複数存在する可能性があり、コンパイラは最終的にそれらを 1 つに結合します。
(たとえば、同じ名前で 2 つの名前空間を定義すると、展開後に両方の空間のメンバーを使用できます)
2: C++ の入力と出力
コード:
例証します:
① cout 標準出力オブジェクト(コンソール)、cin 標準入力オブジェクト(キーボード)を使用する場合は、<iostream> ヘッダファイルをインクルードし、名前空間の使用方法に従って std を使用する必要があります。
②これには、クラスとオブジェクト、演算子のオーバーロード、IO フロー、関数のオーバーロードに関する知識が含まれますが、最初に全体的な印象を持っておくだけでよく、その後の学習でここでの質問に 1 つずつ答えていきます。
●cout と cin はグローバル ストリーム オブジェクト、endl は改行出力を意味する特殊なC++シンボルで、すべて <iostream>ヘッダ ファイルに含まれます。
● << はストリーム挿入演算子、 >> はストリーム抽出演算子です。● 入出力にはC++ を使用する方が便利で、 printf/scanf の入出力のようにフォーマットを手動で制御する必要がありません。C++の入力と出力は変数の型を自動的に識別できます (基本的に関数のオーバーロード)。③初期の標準ライブラリでは、すべての関数がグローバルドメインで実装され、.h接尾辞が付いたヘッダファイルで宣言されており、使用する際には対応するヘッダファイルをインクルードするだけで済みましたが、後にstd名前空間に実装されました。C ヘッダー ファイルと区別するため、また名前空間を正しく使用するために、C++ ヘッダー ファイルには .h が含まれないことが規定されており、古いコンパイラ (vc 6.0) も <iostream.h> をサポートしています。形式であり、以降のコンパイラではサポートされていないため、 <iostream>+std の方法を使用することをお勧めします。
3: 関数のオーバーロード
1.コンセプト
これは関数の特殊なケースです。C ++ では、同じ名前を持つ複数の関数を同じスコープ内で宣言できます。同じ名前を持つこれらの関数の仮パラメータ リスト(パラメータ番号、型、または型の順序) は異なります。同様の機能でデータを処理するためによく使用される、さまざまな種類の問題。
2. 例
コード:
#include <iostream> using namespace std; 函数重载 void fun(int x, int y) { cout << "int x,int y" << endl; } void fun(double x, double y) { cout << "double x,double y" << endl; } void fun() { cout << "NULL" << endl; } int main() { fun(2, 0); //参数类型不同 fun(2.0, 0.0); //参数个数不同 fun(); return 0; }
注: 関数の戻り値が異なっていても、関数のオーバーロードにはなりません。
3. C++ では関数のオーバーロードがサポートされているのに、C ではサポートされていないのはなぜですか?
実際、主な文は次のとおりです。C++ には、関数名を変更するための独自のルールがあります。
C/C++ プログラムの作成には、前処理、コンパイル、アセンブル、およびリンクが必要です。
①前処理:マクロ置換、ヘッダファイル展開、コメント削除(スペース置換)を行います。
② コンパイル: コードをアセンブリコードに変換します (この段階では主に構文解析、シンボルの要約、
字句解析、意味解析)。
③アセンブリ:アセンブリコードをバイナリ機械命令に変換し、シンボルテーブルを生成します。
④ リンク: コンパイルが完了すると、対応するソース ファイルがターゲット ファイルに生成され、リンク段階ではこれらのターゲット ファイルを変換します。
リンクを作成します(手順は複雑です)。
このプロセスの実装の詳細についてはあまり気にする必要はありません。重要な点はシンボルの要約とシンボル テーブルの生成です。
[1] まずC 言語のコードを見てみましょう
main.c ファイルには Add 関数の定義はありませんが、ステートメントはあり、構文エラーはなく、コンパイルは通過できます。
Add.c ファイルには、Add 関数の特定の実装が含まれています。
アセンブリが完了すると、2 つのソース ファイルによって対応するシンボル テーブルが生成されます。
シンボル テーブルはリンク処理中にマージされます。main.obj (main.c アセンブリが完了した後に生成されるオブジェクト ファイル) には Add 関数の定義がありませんが、Add.obj にはあり、最終的に にマージされます。 _Add(0x200)、Add 関数のアドレスを見つけて呼び出すことができます。
上記を踏まえ、同じ名前の関数をもう1つ定義すると、生成されたシンボルテーブル内の2つの関数アドレスが有効となり、どちらを呼び出せばよいのか区別できなくなり、リンクエラーが発生します。
同じシンボル名による競合のため、C言語ではこの状況に対処できないことは容易にわかりますが、シンボルテーブル生成時に関数のパラメータに応じて異なるシンボル名を生成すれば、この状況は解決できないでしょうか? ?
[2] 上記の状況を C++ に置き換えます
このことから、C 言語では同じ名前の関数を区別する方法がないため、オーバーロードをサポートできないことがわかりました。C ++ は関数の変更、パラメータが異なれば変更名も異なり、オーバーロードもサポートされます。
戻り値は変更ルールに含まれていないため、戻り値が異なるだけで関数のオーバーロードを構成することはできません。
4: デフォルトパラメータ
1.コンセプト
デフォルトパラメータは、関数の宣言または定義時に関数のパラメータのデフォルト値を指定します。関数を呼び出すとき、実パラメータが指定されていない場合は、仮パラメータのデフォルト値が採用され、それ以外の場合は、指定された実パラメータが使用されます。
2. 例
3. デフォルトパラメータの分類
【1】全てのデフォルトパラメータ
【2】セミデフォルトパラメータ
4.注意点
①セミデフォルトパラメータは右から左へ順番に与える必要があり、交互に与えることはできません。
②デフォルトパラメータは関数宣言と定義に同時に指定することはできません。デフォルトパラメータは宣言でのみ設定することをお勧めします。
③デフォルト値は定数およびグローバル変数である必要があります