1.名前空間:
名前空間は新しいスコープを定義し、その中のすべてのコンテンツはその名前空間に制限されます。
この目的:名前の競合や名前の汚染を回避するため。
名前空間の定義方法:
- 一般:
namespace N
{
int a;
int ADD(int left, int right)
{
return left + right;
}
}
- ネストされた定義:
namespace N
{
int a;
int ADD(int left, int right)
{
return left + right;
}
namespace N1
{
int a;
int ADD(int left, int right)
{
return left + right;
}
}
}
- 同じファイルに、同じ名前の名前空間が複数あり、コンパイラーは最終的に1つの名前空間にマージされます
namespace N
{
int a;
int ADD(int left, int right)
{
return left + right;
}
}
namespace N
{
int c;
int d;
}
注: 3番目の方法は、同じ名前空間であり、異なる場所に書き込まれ、最終的にマージされます。同じ変数または関数名は使用できません(パラメーターの型はまったく同じです)。そうしないと、再定義が発生します。
名前空間の使用:
- 以下
::
を使用したN::变量/函数
:N::c;
using N(命名空间名):: 变量/函数
頻繁に使用される名前空間の場合など、特定の変数または関数の使用は、そのまま使用できます。このようにして、変数は現在のファイルで「グローバル変数」になり、プロジェクト全体で関数を直接呼び出すことができます。
といった:
using N::ADD;// ②
using N::a;
int main()
{
N::c;//①
return 0;
}
using namespace N(命名空间);
名前空間変数または関数を使用すると、かなり頻繁に使用できます。名前空間のすべてのメンバースコープは、ファイルのグローバルな役割と見なされます。
2.デフォルトのパラメーター:
デフォルトのパラメータは、関数を宣言または定義するときにパラメータのデフォルト値を指定することです。関数が呼び出されたときに、実パラメータが指定されていない場合はデフォルト値が使用され、それ以外の場合は指定された実パラメータが使用されます。
デフォルトのパラメータタイプ:
- 完全なデフォルトパラメータ:すべての関数パラメータにはデフォルト値があります。
int ADD(int first = 1, int second = 2, int third = 3)
{
return first + second + third;
}
- 準デフォルトパラメータ:一部の関数パラメータのみにデフォルト値があります。
int ADD(int first, int second, int third = 3)
{
return first + second + third;
}
注意:
- セミデフォルトパラメータは、右から左に指定する必要があります。
- デフォルトのパラメータを関数の宣言と定義に同時に含めることはできません。
- デフォルト値は定数またはグローバル変数でなければなりません
関数の宣言と定義だけで指定できます。繰り返し表示される場合は、デフォルトパラメータの再定義が表示されます。
通常、デフォルトのパラメーターのデフォルト値を関数宣言で指定することをお勧めします。
3.関数のオーバーロード:
関数のオーバーロード:C ++では、同じ名前の同じような関数を持ついくつかの関数が同じスコープで宣言されます。同じ名前のこれらの関数の仮パラメーターリスト(パラメータータイプ、パラメーターの数、パラメーターの順序)が異なります。
パラメータリストのさまざまな症状:
- パラメーターの数が異なります。パラメーターの数が異なる同じ名前の次の2つの関数は、関数のオーバーロードを構成します。
int ADD(int right, int left)
{
return right + left;
}
int ADD()
{
return 10;
}
- 異なるパラメーターの種類:次の同じ名前の2つの関数には異なるパラメーターの種類があり、関数のオーバーロードを構成します。
int ADD(int right, int left)
{
return right + left;
}
double ADD(double right,double left)
{
return right + left;
}
- パラメータタイプの順序が異なります。同じ名前の次の2つの関数では、パラメータタイプの順序が異なります。これは、関数のオーバーロードを構成します。
double ADD(int right, double left)
{
return right + left;
}
double ADD(double right, int left)
{
return right + left;
}
そのようなコード:
int ADD(int right, int left)
{
return right + left;
}
double ADD(double right, double left)
{
return right + left;
}
int main()
{
ADD(1, 2.2);
return 0;
}
このコードにはどのようなエラーが表示されますか?
関数呼び出しの過程で、仮パラメーターはインスタンス化されますが、完全に一致する型はありません。暗黙的な型変換が行われます。int->double 或者double->int
入力しますが、上記の呼び出しでは、両方の変換を実行できることがわかります。コンパイラーはどちらを選択するかわかりません。エラーになります。
VS2017でのエラー報告:
このエラーは、あいまいさ|あいまいさと呼ばれます。
関数のオーバーロード呼び出しの原則:コンパイル段階で呼び出す関数を決定する
- コンパイル段階では、コンパイラーはタイプを推定し、呼び出す推定結果に従ってタイプに一致する関数を見つけます。
- タイプが完全に一致する関数がある場合は、直接呼び出します。
- 型が完全に一致する関数がない場合は、暗黙的な型変換が実行されます。
- 暗黙の型変換の後に対応する関数(あいまいさなし)がある場合、それが呼び出されます。
- 曖昧さがないか、不明確な場合は、エラーが報告されます。
したがって、ADD(1、2.2)を実行すると、あいまいさ、複数の変換、およびコンパイラエラーが発生します。
関数の戻り値の型は異なり、関数のオーバーロードを構成しません。
int ADD(int right, int left)
{
return right + left;
}
double ADD(int right, int left)
{
return right + left;
}
これは関数のオーバーロードを構成しません。
C言語が関数のオーバーロードをサポートしないのはなぜですか?C ++は関数のオーバーロードをサポートしていますか?
VS環境を見てみましょう。
int ADD(int right, int left);
int main()
{
ADD(1, 2);
return 0;
}
関数定義がない場合、エラーが報告されます。
C ++では、
エラーは次のとおりです。C言語では、エラーは次のとおりです。
上記のコードは同じですが、コンパイラーはコンパイル時に下部で異なる名前を使用します。
C言語:_
関数名にC ++を追加するだけ:関数名をと解釈します?ADD@@YAHHH@Z
。
C ++の場合、戻り値の型はdouble
、パラメーターの型はdouble
、関数名は何ですか?
Linux環境での状況を見てみましょう:
C ++:
C言語:
C言語では、関数の変更が比較的簡単であることがわかります。C ++は関数の装飾に固有であり、Linuxでは、関数名の長さと関数のパラメータータイプの最初の文字が含まれます。
したがって、C言語は関数を比較的簡単に変更するため、関数のオーバーロードをサポートしていません。同じ名前の関数がある場合、再定義が行われます。C ++では、関数パラメーターの型も変更されます。同じ名前の関数のパラメーターリストが異なると、基礎となる説明も異なります。
C言語とC ++関数の違いは何ですか?
- 戻り値のタイプ:
C言語の場合:関数には戻り値の型がなく、システムはデフォルトでint型を返します。
C ++:戻り値の型を取得する必要があります。それ以外の場合、プログラムはエラーを報告します。
- 関数パラメーター:
C言語の場合:関数にはパラメーターがありませんが、呼び出し時にパラメーターが渡され、コンパイラーはそれをコンパイルできます。
C ++では、関数にはパラメーターがなく、呼び出し時にパラメーターが渡され、コンパイラーはそれをコンパイルできません。
- C ++関数パラメーターはデフォルト値を持つことができます:デフォルトのパラメーター
- 関数の命名規則は異なります。C++は関数のオーバーロードをサポートしていますが、C言語はサポートしていません
C ++コンパイラーは、C言語コンパイラーよりも厳密な構文検出を備えています。
4.見積もり:
参照は、現在の既存の変数のエイリアスです。コンパイラは、参照用のスペースを開きませんが、参照された変数とメモリスペースを共有します。
参照変数と参照変数は同じメモリ空間を共有します。
データが変更されると、参照される変数も変更されます。
参照型は変数型と一致している必要があります。
引用されたメモ:
- 定義時に初期化する必要があります。つまり、参照する変数を指定します。
- 変数は複数の参照を持つことができます。つまり、エンティティには複数のエイリアスがあります。
- エンティティを参照した後、他のエンティティを参照することはできません。
定数を参照するときは、constも追加する必要があり、エンティティを参照で変更することはできません。
int main()
{
double d = 12.56;
const int& rd = d;
return 0;
}
上記のコードは正常に引用できます。しかし問題があります:
どうしてこれなの?
参照変数は、参照エンティティのタイプと一致します。doubleとintの間には暗黙的な型変換があり、doubleはintに変換されます。
rdはdを参照し、コンパイラーは遷移として一時スペースを作成します。rdがこの一時スペースを参照するようにします。
ただし、このスペースのアドレスは通常の状況では不明であり、変更できません。したがって、この空間は恒常性(一定の特性)を持っています。
rdは定数を引用することと同じです。constを追加する必要があります。
参照アプリケーションシナリオ:
- コードは簡潔にしてください。
- 関数パラメータを作成します。
- 関数の戻り値を実行します。
関数の戻り値に注意してください。
- 返されたオブジェクトがシステムに返されている場合、参照によって返すことはできません。それ以外の場合は、不正な領域が返されます。
- 戻されたオブジェクトがシステムに戻されない場合は、参照による戻りを使用できます。
関数の値渡しと参照渡しの比較:参照渡しは、値渡しよりもはるかに高速です。これは、参照による仮パラメーターのインスタンス化のプロセスがなく、仮パラメーターがエンティティーの単なるエイリアスであり、パラメーターのスタックによるオーバーヘッドが減少するためです。はるかに高速。
ポインターによる関数の受け渡しと参照による受け渡しの比較:2つの効率は似ています。
void Swap(int& right, int& left)
{
int tmp = right;
right = left;
left = tmp;
}
void Swap(int *right, int *left)
{
int tmp = *right;
*right = *left;
*left = tmp;
}
int main()
{
int a = 10;
int b = 20;
Swap(a, b);
Swap(&a, &b);
return 0;
}
逆アセンブル:
2つのコードによって実行される操作が同じであることがわかりました。参照はポインタの方法で操作されます。
これは、下部にある参照操作とポインタによって実装されます。
参照とポインターの違い:
- 概念的な観点から:
Reference:は変数のエイリアスであり、コンパイラーはそのためのスペースを開きません。参照とエンティティはスペースを共有します。
ポインター:コンパイラーはそのためのスペースを割り振り、ポインターはアドレスを指します。 - 最下位レベルから:参照とポインターの間に違いはありません-参照はポインターです
- 特徴的な観点から:
1.参照を初期化する必要があり、ポインタは必要ありません
2.エンティティが参照されると、他のエンティティを参照できなくなります。ポインタは、タイプと一致する任意のアドレスを指すことができ
ます。3. NULL参照はありませんが、NULLポインタがあります
。4. sizeofでは、参照の結果は参照タイプのサイズであり、ポインタは32ビットプラットフォームでは常に4バイトです
。5.からの参照エンティティに1を加え、1を加えると、ポインタはそのタイプのサイズに1を加えます。6。
マルチレベルポインタはありますが、マルチレベル参照はありません
。7 。エンティティにアクセスする場合、ポインタを逆参照する必要があり、参照を直接使用できます
。8。参照比率ポインタは比較的安全です