- 現代C++語言核心特性解析
- 謝丙堃
- 17字
- 2021-09-27 17:49:49
第2章 內聯和嵌套命名空間(C++11~C++20)
2.1 內聯命名空間的定義和使用
開發一個大型工程必然會有很多開發人員的參與,也會引入很多第三方庫,這導致程序中偶爾會碰到同名函數和類型,造成編譯沖突的問題。為了緩解該問題對開發的影響,我們需要合理使用命名空間。程序員可以將函數和類型納入命名空間中,這樣在不同命名空間的函數和類型就不會產生沖突,當要使用它們的時候只需打開其指定的命名空間即可,例如:
namespace S1 {
void foo() {}
}
namespace S2 {
void foo() {}
}
using namespace S1;
int main()
{
foo();
S2::foo();
}
以上是命名空間的一個典型例子,例子中命名空間S1
和S2
都有相同的函數foo
,在調用兩個函數時,由于命名空間S1
被using
關鍵字打開,因此S1
的foo
函數可以直接使用,而S2
的foo
函數需要使用::來指定函數的命名空間。
C++11標準增強了命名空間的特性,提出了內聯命名空間的概念。內聯命名空間能夠把空間內函數和類型導出到父命名空間中,這樣即使不指定子命名空間也可以使用其空間內的函數和類型了,比如:
#include <iostream>
namespace Parent {
namespace Child1
{
void foo() { std::cout << "Child1::foo()" << std::endl; }
}
inline namespace Child2
{
void foo() { std::cout << "Child2::foo()" << std::endl; }
}
}
int main()
{
Parent::Child1::foo();
Parent::foo();
}
在上面的代碼中,Child1
不是一個內聯命名空間,所以調用Child1
的foo
函數需要明確指定所屬命名空間。而調用Child2
的foo
函數則方便了許多,直接指定父命名空間即可。現在問題來了,這個新特性的用途是什么呢?這里刪除內聯命名空間,將foo
函數直接納入Parent
命名空間也能達到同樣的效果。
實際上,該特性可以幫助庫作者無縫升級庫代碼,讓客戶不用修改任何代碼也能夠自由選擇新老庫代碼。舉個例子:
#include <iostream>
namespace Parent {
void foo() { std::cout << "foo v1.0" << std::endl; }
}
int main()
{
Parent::foo();
}
假設現在Parent
代碼庫提供了一個接口foo
來完成一些工作,突然某天由于加入了新特性,需要升級接口。有些用戶喜歡新的特性但并不愿意為了新接口去修改他們的代碼;還有部分用戶認為新接口影響了穩定性,所以希望沿用老的接口。這里最直接的辦法是提供兩個不同的接口函數來對應不同的版本。但是如果庫中函數很多,則會出現大量需要修改的地方。另一個方案就是使用內聯命名空間,將不同版本的接口歸納到不同的命名空間中,然后給它們一個容易辨識的空間名稱,最后將當前最新版本的接口以內聯的方式導出到父命名空間中,比如:
namespace Parent {
namespace V1 {
void foo() { std::cout << "foo v1.0" << std::endl; }
}
inline namespace V2 {
void foo() { std::cout << "foo v2.0" << std::endl; }
}
}
int main()
{
Parent::foo();
}
從上面的代碼可以看出,雖然foo
函數從V1
升級到了V2
,但是客戶的代碼并不需要任何修改。如果用戶還想使用V1
版本的函數,則只需要統一添加函數版本的命名空間,比如Parent::V1::foo()
。使用這種方式管理接口版本非常清晰,如果想加入V3
版本的接口,則只需要創建V3
的內聯命名空間,并且將命名空間V2
的inline
關鍵字刪除。請注意,示例代碼中只能有一個內聯命名空間,否則編譯時會造成二義性問題,編譯器不知道使用哪個內聯命名空間的foo
函數。
- Mobile Application Development:JavaScript Frameworks
- Learning Cython Programming
- 新一代通用視頻編碼H.266/VVC:原理、標準與實現
- 零基礎玩轉區塊鏈
- INSTANT FreeMarker Starter
- 劍指Java:核心原理與應用實踐
- ExtJS高級程序設計
- Spring MVC+MyBatis開發從入門到項目實踐(超值版)
- Cocos2d-x Game Development Blueprints
- Spring 5 Design Patterns
- MySQL數據庫應用實戰教程(慕課版)
- Getting Started with RethinkDB
- Mastering PostgreSQL 11(Second Edition)
- HTML5 and CSS3:Building Responsive Websites
- R Data Visualization Cookbook