C语言程序员程序园

c++基础(namespace)

2019-05-02  本文已影响13人  zidea
Cplusplus-tutorial-in-hindi.jpg

有关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();

如果只想使用命名空间来简化对Bprint调用,而不涉及 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();
}

Hello

同时存在两个 namespace 时候,会调用谁的print函数呢?

using namespace apple;
using namespace orange;

看结果调用的是 orange 的 print

olleH

为什么呢,这要从"Hello"到底是什么类型来说起,"Hello" 是 char* 的类型,在没有orangeprint的时候,会调用 applevoid print(const std::string &text),这里是隐式将char*转换为 std::string 类型,但是一旦有了rangeprint 函数因为其参数类型 const char*"hello" 匹配更好所以执行了orangeprint而不是 appleprint

但是不是表明我们不使用 using namespace ,存在就意义,在自己的库中是可以使用 using name

上一篇 下一篇

猜你喜欢

热点阅读