記事ディレクトリ
名前空間の概念
在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存 在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化, 以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。
多くの人が初めて C++ に触れるとき、行の出力が hello world
次のように記述されることを知っています。
#include
名前空間 std を使用します。
int main()
{ cout << “hello world” << endl; }
しかし、iostream と namespace std とは何ですか、そしてこのコード行でどのような役割を果たしているのかと尋ねると、多くの初心者は基本的に答えることができず、書き方は知っているだけで意味は知りません。
それでは、名前空間の概念を理解しましょう
大家都知道C++是在c语言基础上建立的,c语言很多地方存在很多缺陷的,C++就创建了一个命名空间的概念来弥补这一缺陷
这一缺陷是什么呢?创建一个全局变量 int rand = 0 ,你只引入了头文件 <stdio.h> ,利用printf打印出rand,不会产生任何问题。可当你再引用了 <stdlib.h> ,再次运行程序就会出现问题
这里报错,显示rand重定义,这里的问题叫做命名冲突,因为 stdlib.h 这个库里面已经定义了rand,且定义成的一个函数,而我们这个全局变量rand是int类型的元素,系统在识别这个rand的时候就会找到两个rand,它不知道去打印哪一个,当然这里刚好rand在库里面是个函数 且与%d发生冲突,显示两个错误
C 言語では、この問題を解決する最も単純かつ大雑把な方法は、ライブラリ内の同じ名前の変数との名前の競合を防ぐために変数名を変更することです。これで問題は確実に解決できますが、グループで作業して完了する必要がある場合は、チーム内のプロジェクトです。各グループの個人変数は同じです。このときどうしますか? 直接喧嘩することはできません。これは作業効率を大幅に低下させ、チームの雰囲気に影響を与えるため、この方法は当然ですお勧めできません。
命名空间
C 言語ではこの問題を解決できないため、これを解決するためにC++ が提案されました.
ここでキーワードを紹介しますnamespace
. その機能は、作成された rand 変数を保護するドメインを作成することです. 以下はコードの実装です。
namespace Yuan
{
int rand = 0;
}
int main()
{
printf("%d\n", rand);
}
namespace
以下の名前は任意で構いません。覚えていれば
名前の衝突はありません。main に出力されるのはライブラリ関数内の rand です (正確には、グローバル ドメインにアクセスして rand を見つけます)。
元の範囲内でランドを出力したい場合は、 rand の前に追加する必要がありますYuan::
namespace Yuan
{
int rand = 0;
}
int main()
{
printf("%d\n", Yuan::rand);
}
namespace
作成されるのは Yuan という名前のローカル ドメインですが、ここで C 言語のグローバル変数とローカル変数を確認する必要があります。
int i = 0;
int main()
{
int i = 1;
printf("%d", i);
}
ここで質問ですが、ここに書かれている i は 0 ですか、それとも 1 ですか?
答えは 1 です。ここで 1 は満たされます
就近原则
。出力結果は 1 です。これは、直接アクセスされるローカル ドメイン内のローカル変数 i です。
しかし、ローカル ドメインのグローバル変数 i にアクセスしたい場合はどうすればよいでしょうか?
i の前に追加する必要があります
::
int i = 0;
int main()
{
int i = 1;
printf("%d\n", ::i);
printf("%d\n", i);
}
::
これはドメイン演算子と呼ばれ、その機能は i を検索するドメインを指定することです。::
ここの左側は空白であり、グローバル ドメインで検索されることを意味します。
したがって、名前の競合の問題は、名前空間の概念を使用して簡単に解決できます。ABCの3つのグループがあり、各グループが書き込んだ変数は全てそれぞれが定義した名前空間に格納され、それぞれnodeA、nodeB、nodeCに名前空間が転送されます。それぞれの名前空間に同じ変数があっても受信されません。あらゆる影響
名前空間の定義
1. 通常の名前空間定義
変数、関数、型などを名前空間で定義できます。
namespace Yuan
{
int rand = 0;
void func()
{
printf("func()\n");
}
struct TreeNode
{
struct TreeNode* left;
struct TreeNode* right;
int val;
};
}
int main()
{
printf("%p\n", rand);
printf("%p\n", Yuan::rand);
Yuan::func();
struct Yuan::TreeNode node;
return 0;
}
2. 名前空間は入れ子にすることができます
名前空間は、ループ ステートメントと同様にネストできます。
namespace sql
{
int a = 0;
namespace Yuan
{
int rand = 0;
void func()
{
printf("func()\n");
}
struct TreeNode
{
struct TreeNode* left;
struct TreeNode* right;
int val;
};
}
}
int main()
{
printf("%p\n", rand);
printf("%p\n", sql::Yuan::rand);
sql::Yuan::func();
struct sql::Yuan::TreeNode node;
return 0;
}
3. 同じ名前を持つ複数の名前空間が同じプロジェクト内に存在することが許可され、コンパイラは最終的にそれらを同じ名前空間に合成します。
これを理解するにはどうすればよいでしょうか? たとえば、プロジェクトに、多くの変数と型を含む Stack.h (スタック)、Stack.cpp (スタック)、Queue.h (キュー)、Queue.cpp (キュー) を追加しました。 , など 次に、それらを名前空間に入れる必要があります。名前の競合が心配になります。それに対処する方法は次の
4 つのファイルに毎回名前空間を定義し、すべてをファイルに入れます。名前空間に入れます。これら 4 つ名前空間は同じ名前を持っていますが、同じファイル内に存在しません。コンパイラはそれらを自動的に 1 つの名前空間にマージするため、名前の競合を心配する必要はありません。
namespace Yuan
{
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top; // 栈顶的位置
int capacity; // 容量
}ST;
}
#include "Stack.h"//栈
#include "Queue.h"//队列
int main()
{
Yuan::ST st;
Yuan::StackInit(&st);
Yuan::Queue q;
Yuan::QueueInit(&q);
}
名前空間の使用
1. 名前空間名とスコープ修飾子の追加
int main()
{
printf("%d\n", Yuan::a);
return 0;
}
ドメイン スコープによる名前空間の使用についてはすでに紹介しました。これは、名前空間を使用する最も基本的で簡単な方法でもあります。ただし、この方法は、名前空間が頻繁に使用される場合には少し面倒になります。ここでは利用できないかもしれません。ドメイン演算子の追加, しかし、そこに追加しなかった場合、多くのバグが発生したため、次の 3 つの方法があります。
2. using を使用して名前空間のメンバーを導入します
using Yuan::b;
int main()
{
printf("%d\n", Yuan::a);
printf("%d\n", b);
return 0;
}
3. 名前空間を使用して使用する 名前空間名の紹介
using namespce N;
int main()
{
printf("%d\n", Yuan::a);
printf("%d\n", b);
Add(10, 20);
return 0;
}
4. 名前空間を使用して使用する std C++ 標準ライブラリの名前空間の概要
最初の 2 つは比較的保守的です。これは非常に大胆で、C++ 標準ライブラリ全体を直接拡張します。特定の競合を大幅に回避しますが、すべてをこの方法で拡張すると競合のリスクが生じる可能性があるため、そうではありません全て直接展開することを推奨します。使用したい場合は次のように記述します。
#include<iostream>
//using namespace std
int main()
{
std::cout << "hello world" << std::endl;
return 0;
}