命名空間的引入
1、C語言如何解決名稱衝突
(1)大項目中會有很多C文件,項目中的全局變量和函數理應能互相訪問,因此名稱衝突是客觀存在。
(2)C中解決名稱衝突的辦法是:
第一:同一個C文件不要太大,由一個人寫;
第二:每個C文件(或幾個C文件構成的一個模塊)中所有全局變量和函數前加統一的唯一前綴;
第三:不需要文件外訪問的全局變量和函數前面都加static
2、命名空間的引入
(1)命名空間namespace,是C++引入的一種解決全局變量和函數名衝突的機制
(2)C語言沒有namespace,但是C++及之後的java, python等都有
(3)namespace的關鍵點有2個:一是如何解決名稱衝突,二是如何合法訪問變量
3、命名空間如何解決問題
(1)爲實現命名空間機制,C++引入了namespace關鍵字,定義格式爲namespace xx{};
(2)一個特定名稱的namespace的一對大括號內部定義的變量、函數、類等均屬於該命名空間內
(3)在命名空間內部互相引用時可以直接使用變量名、函數名等
(4)跨命名空間互相引用時必須同時指定被引用方的命名空間名和變量名函數名纔可以找到
(5)命名空間看起來就好像一種前綴
(6)命名空間本質上其實是對全局變量和函數在一定範圍內鏈接屬性的更改和控制
namespace的初級定義和使用
1、同一文件內定義和使用命名空間
(1)namespace的三種引用方法
namespace NS1
{
void func2(void)
{
}
void func1(void)
{
func2();
}
};
//using NS1::func1; // 第二種訪問方式
//using namespace NS1; // 第三種訪問方式
int main(void)
{
NS1::func1(); // 第一種訪問方法
func1();
return 0;
}
2、不同C文件間定義和使用命名空間
3、默認命名空間
(1)又叫全局命名空間
(2)其他命名空間引用默認命名空間中的方法::f();
void func5(void);
namespace NS1
{
void func2(void)
{
::func5(); // 表示func5定義和聲明在默認命名空間中
}
};
int main(void)
{
func5();
return 0;
}
void func5(void)
{
}
4、匿名命名空間的定義和使用
std和cout的引入
(1)std是C++標準庫定義好的一個namespace
(2)cout是std這個namespace下的一個標準輸出工具,類似於C中的printf
hello.cpp
#include <iostream>
using namespace std;
namespace
{
extern void func2(void); //聲明瞭hello2.cpp中的匿名空間裏面的函數
}
namespace NS
{
void func1(void)
{
func2(); //有警告,連接時發生錯誤
}
};
int main(void)
{
NS::func1();
return 0;
}
hello2.cpp
#include <iostream>
using namespace std;
namespace
{
void func2(void)
{
cout << "func2 from anonymous namespace" << endl;
}
}
匿名命名空間的價值
- 匿名命名空間中的符號純文件內部使用,不需要被外部引用
- 匿名命名空間效果類似於全局變量和函數加static,但是比C中的static使用範圍廣
- 匿名命名空間的用法邏輯上符合整個命名空間的一貫原則
5、嵌套命名空間的定義和使用
#include <iostream>
using namespace std;
namespace NS1
{
namespace NS2
{
void func1(void)
{
cout << "NS1::NS2::func1." << endl;
}
void func2(void)
{
cout << "NS1::NS2::func2" << endl;
}
}
void func2(void)
{
cout << "NS1::func2." << endl;
}
}
int main(void)
{
NS1::NS2::func2(); //輸出NS1::NS2::func2
NS1::func2(); //輸出NS1::func2.
return 0;
}