一、命名空間 namespace
1、命名空間基本概念
命名空間 namespace 又稱為 名字空間 , 名稱空間 , 名域 , 作用域 , 是 C++ 語言 對 C 語言 的擴展 之一 ;
C++ 中的 命名空間 namespace 指的是 標識符 的 可見范圍 , C++ 標準庫中的 所有 標識符 , 都定義在 std 命名空間中 ;
2、名稱概念
命名空間 英文名稱是 " namespace " , name 是 名字 , 名稱 的意思 , space 空間 ; 這里的 名稱 name 可以是
- 符號常量 名稱
- 變量 名稱
- 宏定義 名稱
- 函數(shù) 名稱
- 結(jié)構(gòu)體 名稱
- 枚舉 名稱
- 類 名稱
- 對象 名稱
在命名空間中 , 可以定義上述 符號常量 , 變量 , 宏定義 , 函數(shù) , 結(jié)構(gòu)體 , 枚舉 , 類 , 對象 等內(nèi)容 ;
命名空間 不是專門定義 標識符名稱的 , 而是可以定義 C++ 中出現(xiàn)的所有語法元素 ;
4、C 語言的命名空間
在 C 語言中 , 只有一個命名空間 namespace , 就是 全局作用域 ;
C 語言中 , 所有的 全局標識符 , 都共享 同一個 命名空間 namespace ( 作用域 / 名字空間 ) ;
這就使得 , 在 C 語言開發(fā)中 , 標識符 定義 經(jīng)常出現(xiàn)沖突 , 在 C 語言 的 大規(guī)模開發(fā)中 , 不同的團隊 開發(fā)者之間不好協(xié)調(diào) ;
- 示例 1 : 開發(fā)者 A 定義了 全局變量 name , 開發(fā)者 B 也定義了 全局變量 name , 這就導致了二者之間出現(xiàn)了沖突 ;
- 示例 2 : C 語言模塊 1 中定義了 全局變量 name , 在 C 語言模塊 2 中定義了相同名稱的全局變量 name , 如果 主程序 同時導入了這兩個模塊 , 就出現(xiàn)了沖突 ;
鑒于上述問題 , 在 C++ 中引入了新的概念 , 命名空間 namespace , 解決上述 標識符名稱沖突的問題 ;
3、命名空間避免標識符沖突
C++ 被設(shè)計用于開發(fā) 大規(guī)模 的程序 , 參與開發(fā)的 開發(fā)者 或 團隊 可能很多 , 每個開發(fā)者都要定義各種 變量 函數(shù) 類 對象 等 , 涉及到大量的 標識符 名稱 ;
為了避免名稱沖突 , 引入了 命名空間 namespace 關(guān)鍵字 , 每個開發(fā)者將自己寫的 名稱 定義到 專門的空間中 , 這個空間就是 命名空間 namespace ;
命名空間 namespace 可以避免 定義 各種 變量名稱 / 函數(shù)名稱 等名稱時 , 出現(xiàn) " 名稱沖突 " 問題 ;
在 命名空間 中 , 開發(fā)者可以 將 各種 常量 / 變量 / 宏定義 / 函數(shù) / 結(jié)構(gòu)體 / 枚舉 / 類 / 對象 等 內(nèi)容 , 組織在一起 , 避免與 其它 命名空間 或 全局標識符 發(fā)生沖突 ;
命名空間 可以 將 整體的 全局作用于 切割成 不同的區(qū)域 , 也就是 不同的區(qū)域 使用 不同的 命名空間 ;
不同的 命名空間 中 , 可以定義 相同名稱的 標識符 , 不會出現(xiàn)沖突 ;
C++ 中 的 默認命名空間是 全局作用域 , 訪問 全局作用域 中的標識符 ,
- 可以直接訪問 ,
- 也可以使用
::標識符
進行訪問 ;
命名空間 是 可以嵌套的 , 可以在一個命名空間中 , 定義另外一個命名空間 ;
C++ 的命名空間 可以理解為 Java 中的 包名 Package , 在不同的 Package 包 中 , 可以定義相同名稱的 類 ;
二、命名空間定義
1、命名空間基本概念
C++ 命名空間類型 :
- 嵌套命名空間 : 在 命名空間 中可以 嵌套 定義 另一個命名空間 , 內(nèi)層 被 嵌套的 命名空間 可以進一步嵌套 ; 訪問 嵌套 命名空間 標識符 , 需要將 不同層次 的 命名空間都寫上 ;
- 普通命名空間 : 標識符 獨立 的 使用 范圍 , 在 普通命名空間 中定義的標識符 , 可以在 其它命名空間 或 默認的全局命名空間 中使用 ;
2、命名空間定義語法
命名空間定義語法 : 定義 命名空間 需要使用 namespace
關(guān)鍵字 , 將要定義的內(nèi)容 寫在 namespace 命名空間名稱
后的大括號中 ;
namespace 命名空間名稱 {
// 聲明標識符
// 可以是 符號常量 , 變量 , 宏定義 , 函數(shù) , 結(jié)構(gòu)體 , 枚舉 , 類 , 對象 等內(nèi)容
}
命名空間定義示例 :
// 自定義命名空間
namespace MyNamespace {
// 聲明標識符
int myVariable = 10;
void myFunction() {
// 函數(shù)體
cout << "MyNamespace myFunction" << endl;
}
}
3、代碼示例 - 命名空間定義使用
這里要特別注意 , 在下面的代碼中 , 定義了 MyNamespace
命名空間 ,
但是在該 文件 中沒有使用 該 命名空間 , 那么如果要訪問 命名空間 中的內(nèi)容 , 需要添加 MyNamespace ::
前綴 ,
訪問 MyNamespace
命名空間中的 的 myVariable
變量 , 需要使用 MyNamespace::myVariable
代碼訪問 ;
訪問 MyNamespace
命名空間中的 的 myFunction
方法 , 需要使用 MyNamespace::myFunction()
代碼訪問 ;
代碼示例 :
// 包含 C++ 頭文件
#include "iostream"
// 使用 std 標準命名空間
// 該命名空間中 , 定義了很多標準定義
using namespace std;
// 自定義命名空間
namespace MyNamespace {
// 聲明標識符
int myVariable = 10;
void myFunction() {
// 函數(shù)體
cout << "MyNamespace myFunction" << endl;
}
}
int main()
{
cout << "命名空間中的變量 : " << MyNamespace::myVariable << endl;
MyNamespace::myFunction(); // 調(diào)用命名空間中的函數(shù)
// 控制臺暫停 , 按任意鍵繼續(xù)向后執(zhí)行
system("pause");
}
執(zhí)行結(jié)果 :
命名空間中的變量 : 10
MyNamespace myFunction
Press any key to continue . . .
三、命名空間使用
1、命名空間默認訪問方式
如果不導入命名空間 std
, 將 using namespace std;
代碼注釋掉 , 此時就會報錯 , cin
, cout
, endl
都會報 " 未定義標識符 " 錯誤 ;
如果想要在 不聲明 命名空間 的情況下 , 使用 標準流 中的標識符 , 就需要使用
std::cout
std::endl
std::cin
否則 無法訪問 這些 標識符;
代碼如下 : 在下面的代碼中 , 沒有聲明全局命名空間 std
, 要使用 iostream 中的標識符 , 必須加上 std::
前綴 ;
// 包含 C++ 頭文件
#include "iostream"
// 使用 std 標準命名空間
// 該命名空間中 , 定義了很多標準定義
//using namespace std;
int main()
{
// 定義圓半徑 , 周長 , 面積 對應(yīng)的變量
double r = 0, p = 0, a = 0;
// 提示輸入圓半徑
std::cout << "輸入圓半徑 :" << std::endl;
// 從命令行標準輸入得到的數(shù)據(jù) 到 變量 r 指示的內(nèi)存空間中
std::cin >> r;
std::cout << "接收到圓半徑 :" << r << std::endl;
// 計算圓周長
p = 3.14159 * 2 * r;
// 計算圓面積
a = 3.14159 * r * r;
// 打印計算結(jié)果
std::cout << "圓周長為 :" << p << " 圓面積為 : " << a << std::endl;
// 控制臺暫停 , 按任意鍵繼續(xù)向后執(zhí)行
system("pause");
}
執(zhí)行結(jié)果 :
輸入圓半徑 :
10
接收到圓半徑 :10
圓周長為 :62.8318 圓面積為 : 314.159
請按任意鍵繼續(xù). . .
2、使用命名空間
使用命名空間 語法 : 使用如下語法 , 可以 聲明使用一個命名空間 , 可以直接訪問命名空間中的元素 ;
// 使用 指定的 命名空間
using namespace 命名空間名稱;
如果要使用 嵌套的命名空間 , 如 : 命名空間 A 中定義 命名空間 B , 命名空間 B 中定義了 命名空間 C , 則使用如下語法 :
// 使用 指定的 嵌套 命名空間
using namespace A::B::C;
之前的章節(jié)中 , 自定義了 命名空間 MyNamespace ,
// 自定義命名空間
namespace MyNamespace {
// 聲明標識符
int myVariable = 10;
void myFunction() {
// 函數(shù)體
cout << "MyNamespace myFunction" << endl;
}
}
但是 , 使用時 , 必須通過 MyNamespace::myVariable
的形式訪問 命名空間 中的變量 ;
如果想要 直接訪問命名空間元素 , 可以使用上述 語法 , 導入命名空間 :
// 使用自定義的命名空間
// 注意 : 使用命名空間需要在 定義命名空間之后
using namespace MyNamespace;
注意 : 使用 命名空間 需要在 定義命名空間之后 , 否則會報錯 ;
3、使用默認的命名空間
當前的 全局命名空間 就是 默認的 命名空間 , 如果你 沒有在 命名空間 中定義 變量 / 類 / 函數(shù) 等元素 , 而是 直接在 C++ 代碼中直接定義 , 那么這些元素 就是 定義在了 默認的 命名空間 中 ;
將變量定義在 C++ 代碼中 , 就是定義了 全局空間變量 , 就是 默認命名空間 中的變量 ;
調(diào)用 默認命名空間 中的變量 , 可以使用 ::
前綴訪問 ;
代碼示例 :
// 包含 C++ 頭文件
#include "iostream"
// 將變量 定義在了 默認命名空間 : 全局命名空間
int globalVariable = 10;
// 將函數(shù) 定義在了 默認命名空間 : 全局命名空間
void globalFunction() {
std::cout << "globalFunction" << std::endl;
}
int main() {
::globalFunction(); // 調(diào)用全局函數(shù) 默認命名空間中的函數(shù)
::globalVariable = 20; // 修改全局變量 默認命名空間中的變量
std::cout << "::globalVariable : " << ::globalVariable << std::endl;
// 調(diào)用 默認命名空間 中的元素 , 不加域操作符也可以使用
globalFunction(); // 調(diào)用全局函數(shù) 默認命名空間中的函數(shù)
globalVariable = 30; // 修改全局變量 默認命名空間中的變量
std::cout << "globalVariable : " << globalVariable << std::endl;
// 控制臺暫停 , 按任意鍵繼續(xù)向后執(zhí)行
system("pause");
return 0;
}
執(zhí)行結(jié)果 :
globalFunction
::globalVariable : 20
globalFunction
globalVariable : 30
Press any key to continue . . .
4、代碼示例 - 使用命名空間
完整代碼示例 :
// 包含 C++ 頭文件
#include "iostream"
// 使用 std 標準命名空間
// 該命名空間中 , 定義了很多標準定義
using namespace std;
// 自定義命名空間
namespace MyNamespace {
// 聲明標識符
int myVariable = 10;
void myFunction() {
// 函數(shù)體
cout << "MyNamespace myFunction" << endl;
}
}
// 使用自定義的命名空間
// 注意 : 使用命名空間需要在 定義命名空間之后
using namespace MyNamespace;
int main()
{
cout << "命名空間中的變量 : " << myVariable << endl;
myFunction(); // 調(diào)用命名空間中的函數(shù)
// 控制臺暫停 , 按任意鍵繼續(xù)向后執(zhí)行
system("pause");
}
執(zhí)行結(jié)果 :
命名空間中的變量 : 10
MyNamespace myFunction
Press any key to continue . . .
四、標準流 iostream
標準流 iostream 的內(nèi)容 , 都定義在 std 命名空間中 ;
C++ 語言為了與 C 語言 在 頭文件上 進行區(qū)分
- C++ 語言的頭文件沒有 .h 后綴 ;
- C 語言的頭文件有 .h 后綴 ;
1、查看 iostream 頭文件
在代碼中 , " Ctrl + 左鍵 " 點擊 iostream 頭文件 , 即可 跳轉(zhuǎn)到該 標準流 頭文件中 ;
在 Visual Studio 2019 中的 解決方案資源管理器 中 , 雙擊展開 外部依賴項 ,
向下翻 , 就可以找到 iostream 頭文件 ,
2、iostream 頭文件源碼
iostream 頭文件 , 只有 60 行代碼 , 核心的內(nèi)容都定義在 yvals_core.h 和 istream 頭文件中 ;
在 該頭文件 中 , 第 19 行使用了 _STD_BEGIN
宏定義 , 相當于定義 namespace std {
命名空間的開始 , 最后的第 53 行使用的 _STD_END
宏 相當于 命名空間的 定義結(jié)束 }
;
// iostream standard header
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#pragma once
#ifndef _IOSTREAM_
#define _IOSTREAM_
#include <yvals_core.h>
#if _STL_COMPILER_PREPROCESSOR
#include <istream>
#pragma pack(push, _CRT_PACKING)
#pragma warning(push, _STL_WARNING_LEVEL)
#pragma warning(disable : _STL_DISABLED_WARNINGS)
_STL_DISABLE_CLANG_WARNINGS
#pragma push_macro("new")
#undef new
_STD_BEGIN // 開始定義 std 命名空間
#ifdef _M_CEE_PURE
__PURE_APPDOMAIN_GLOBAL extern istream cin, *_Ptr_cin;
__PURE_APPDOMAIN_GLOBAL extern ostream cout, *_Ptr_cout;
__PURE_APPDOMAIN_GLOBAL extern ostream cerr, *_Ptr_cerr;
__PURE_APPDOMAIN_GLOBAL extern ostream clog, *_Ptr_clog;
__PURE_APPDOMAIN_GLOBAL extern wistream wcin, *_Ptr_wcin;
__PURE_APPDOMAIN_GLOBAL extern wostream wcout, *_Ptr_wcout;
__PURE_APPDOMAIN_GLOBAL extern wostream wcerr, *_Ptr_wcerr;
__PURE_APPDOMAIN_GLOBAL extern wostream wclog, *_Ptr_wclog;
#else // _M_CEE_PURE
// OBJECTS
__PURE_APPDOMAIN_GLOBAL extern _CRTDATA2_IMPORT istream cin, *_Ptr_cin;
__PURE_APPDOMAIN_GLOBAL extern _CRTDATA2_IMPORT ostream cout, *_Ptr_cout;
__PURE_APPDOMAIN_GLOBAL extern _CRTDATA2_IMPORT ostream cerr, *_Ptr_cerr;
__PURE_APPDOMAIN_GLOBAL extern _CRTDATA2_IMPORT ostream clog, *_Ptr_clog;
__PURE_APPDOMAIN_GLOBAL extern _CRTDATA2_IMPORT wistream wcin, *_Ptr_wcin;
__PURE_APPDOMAIN_GLOBAL extern _CRTDATA2_IMPORT wostream wcout, *_Ptr_wcout;
__PURE_APPDOMAIN_GLOBAL extern _CRTDATA2_IMPORT wostream wcerr, *_Ptr_wcerr;
__PURE_APPDOMAIN_GLOBAL extern _CRTDATA2_IMPORT wostream wclog, *_Ptr_wclog;
// CLASS _Winit
class _CRTIMP2_PURE_IMPORT _Winit {
public:
__thiscall _Winit();
__thiscall ~_Winit() noexcept;
private:
__PURE_APPDOMAIN_GLOBAL static int _Init_cnt;
};
#endif // _M_CEE_PURE
_STD_END // 結(jié)束定義 std 命名空間
#pragma pop_macro("new")
_STL_RESTORE_CLANG_WARNINGS
#pragma warning(pop)
#pragma pack(pop)
#endif // _STL_COMPILER_PREPROCESSOR
#endif // _IOSTREAM_
3、yvals_core.h 頭文件中 std 命名空間相關(guān)宏定義
在 yvals_core.h 頭文件中 , 定義了 std 命名空間相關(guān)的宏定義 , 如 : _STD_BEGIN
, _STD_END
, _STD
等 ;
// NAMESPACE
#define _STD_BEGIN namespace std {
#define _STD_END }
#define _STD ::std::
4、iostream 使用時一般導入 std 命名空間
在 C++ 代碼中 , 經(jīng)常見到 下面兩行代碼 在一起使用 ,
使用 C++ 的 iostream 標準流時 , 需要使用 #include "iostream"
代碼先導入該標準庫 ;文章來源:http://www.zghlxwxcb.cn/news/detail-659097.html
由于 iostream 頭文件中沒有定義 全局命名空間 , 如果要使用 cin
或者 cout
, 必須加上 std::
前綴 , 如 : std::cin
和 std::cout
;文章來源地址http://www.zghlxwxcb.cn/news/detail-659097.html
// 包含 C++ 頭文件
#include "iostream"
// 使用 std 標準命名空間
// 該命名空間中 , 定義了很多標準定義
using namespace std;
到了這里,關(guān)于【C++】命名空間 namespace 與 標準流 iostream ( 命名空間概念簡介 | 命名空間定義 | 命名空間使用 | iostream 中的命名空間分析 )的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!