有关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 here
void print(const char *text)
在 c++ 中我们可以使用命名空间来对两个相同 symbol 的函数进行区分来解决冲突问题。
namespace A
{
void print(const char *text)
{
std::cout << text << std::endl;
}
} // namespace A
namespace 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 apple
namespace orange
{
void print(const char *text)
{
std::string temp = text;
std::reverse(temp.begin(), temp.end());
std::cout << temp << std::endl;
}
} // namespace orange
using 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
网友评论