有关namespace
也称命名空间,想必大家并不默认,通过增加命令空间来处理同一结构函数的冲突的问题,我们
#include <iostream>#include <string>void print(const char *text){ std::cout << text << std::endl;}void print(const char *text){ std::cout << text << std::endl;}int main(int argc, char const *argv[]){ std::cin.get();}
编译源码报错表示我们重新定义了 print 函数,在 c++ 中具每一个函数都是对应一个 Symbol ,这个 Symbol 是可以表示 class、function 或者是 variable。由于这个两个 print
结构和名称一致,这里结构就是我们定义函数的形参和返回值类型都是相同。在 c++ 中 symbol 是唯一,所以编译时候报下面的错误。
最简单最粗暴就是修改函数名 a_print 和 b_print。不过多数情况我们是和第三方库同名,无法修改库中函数名称。这时候我们即可以使用到命名空间来处理 symbol 冲突的问题。
这里在多说依据在 c 语言中是不支持命名空间的,所以我们看 openGL 的库函数都有前缀 gl_ 通过这种方式进行区分。
namespace2.cpp:9:6: error: redefinition of 'print'void print(const char *text) ^namespace2.cpp:4:6: note: previous definition is herevoid print(const char *text)
在 c++ 中我们可以使用命名空间来对两个相同 symbol 的函数进行区分来处理冲突问题。
namespace A{void print(const char *text){ std::cout << text << std::endl;}} // namespace Anamespace B{void print(const char *text){ std::cout << text << std::endl;}}
使用时候可以通过::
操作符来调用 namespace A 的 print 方法。在调用 class 的静态方法时候我们也可能会用到::
操作符,这是由于 class 本身就提供一个命名空间。
A::print("hello");
namespace 支持嵌套。
namespace A{namespace functions{void print(const char *text){ std::cout << text << std::endl;}} // namespace functions} // namespace A
A::functions::print("hello");
将我们命名空间使用缩小的一个作用域可以在function
内也可以在{}
定义作用域
using namespace A; functions::print("hello"); std::cin.get();
using B::print; print("hello"); B::another_print();
假如只想使用命名空间来简化对B
的print
调用,而不涉及 another_print
,即可以这样来写。
namespace second = B; second::print("hello"); B::another_print();
也可以为命名空间起一个别名namespace second = B;
。
大家习惯会用 namespace 来简化每次都需要输入std
的工作.
#include <iostream>#include <vector>#include <algorithm>#include <functional>void ForEach(const std::vector<int> &values, const std::function<void(int)> &func){ for (int value : values) func(value);}int main(int argc, char const *argv[]){ std::vector<int> values = {1, 2, 3, 2, 1}; auto it = std::find_if(values.begin(), values.end(), [](int value) { return value > 2; }); std::cout << *it << std::endl; int a = 5; auto lambda = [=](int value) mutable { a= 6; std::cout << "value: " << a << value << std::endl; }; ForEach(values, lambda); std::cout << a << std::endl; std::cin.get();}
上面的代码我们每次引用std都会写std::
,假如使用using namespace std;
我们就无需在每一个 std 提供方法前写std::
。using namespace
有肯定的作用域。
假如我们使用using namespace
来简化函数调用前缀,当然对于一个简单项目没有问题,这是好事减少我们输入,但是假如是一个引用第三方库或者这些写许多和标准库同名函数,我们就应该避免使用using namespace
,这样做会让我们和其余阅读代码人 confusing ,这个函数出处。
#include <iostream>#include <string>namespace apple{void print(const std::string &text){ std::cout << text << std::endl;}} // namespace applenamespace orange{void print(const char *text){ std::string temp = text; std::reverse(temp.begin(), temp.end()); std::cout << temp << std::endl;}} // namespace orangeusing namespace apple;// using namespace orange;int main(int argc, char const *argv[]){ print("Hello"); std::cin.get();}
namespace
都有print
方法,但是他们接收参数不同分别apple
的void print(const std::string &text)
而orange
的 print 函数为void print(const char *text)
。apple
的namespace
无疑会输出Hello
。Hello
同时存在两个 namespace 时候,会调用谁的print
函数呢?
using namespace apple;using namespace orange;
看结果调用的是 orange 的 print
olleH
为什么呢,这要从"Hello"
究竟是什么类型来说起,"Hello"
是 char* 的类型,在没有orange
的print
的时候,会调用 apple
的void print(const std::string &text)
,这里是隐式将char*
转换为 std::string 类型,但是一旦有了range
的 print
函数由于其参数类型 const char*
和 "hello"
匹配更好所以执行了orange
的print
而不是 apple
的print
。
但是不是表明我们不使用 using namespace
,存在就意义,在自己的库中是可以使用 using name