如何在C ++中使用namespace :: function选择函数的单个重载?

问题描述 投票:22回答:7

考虑以下C ++代码。

namespace A {
    void f() { // first function
    }

    void f(int) { // second function
    }
}
...
using A::f; // introduces both functions

有没有办法只引入一个功能?

c++ namespaces using
7个回答
18
投票

该行为在标准中有明确定义。

C++03 7.3.3 The using declaration

“......如果名称是重载成员函数的名称,那么所有命名的函数都应该是可访问的。”


8
投票

using关键字将所有名称带入当前范围。所以使用这个当前的代码是不可能的。

但是,您可以将名称部分引入文件,如下所示:

namespace A {
  void f();  // declaration
}
using A::f;
// now only `A::f()` is visible in the subsequent code
// technically `A::f(int)` is not yet visible (thus unusable)

// introduce the other function later on
namespace A {
  void f(int);
}

Demo

编辑:更好的方法是将A::f(int)放在嵌套的namesapce中并引入一个别名(为了方便使用)。

namespace A {
  void f();
  namespace Internal {
    void f(int);
  }
}
using A::f;
namespace A_ = A::Internal;

现在,其他功能也可用作A_::f(int)


3
投票

不是我所知道的。如果有问题,您可以编写包装函数。

void f(int i) { A::f(i); }

2
投票

除了其他答案之外,我还将提供更多示例。

许多用C ++编程的书籍经常通过在源文件的开头添加以下行来公开整个STD命名空间:

using namespace std;

由于可能在某些时候发生的各种冲突,特别是当代码由处理同一任务的许多开发人员提供时,暴露完整的命名空间实际上恰好在现实生活中是一种不好的做法。这种编程风格也违背了面向对象编程的基本规则之一 - 通过封装数据避免暴露超出实际需要的范围。这就是为什么类例如公共和私人成员,getter和setter等等。命名空间只是分组信息的另一种方式。暴露整个std命名空间是违反这个规则的,特别是如果你想使用let,比如说std :: cout,std :: cin和std :: endl。您可以轻松地将使用应用于特定功能,这使您可以更精确地控制,并且更有可能避免在您可能在某些时候使用的多个名称空间中发生命名冲突:

using std::cout;
using std::cin;
using std::endl;

这允许您在没有namespace-prefix的代码中调用cout,cin和endl。如果在某些时候出现命名冲突,那么查看一组using指令要容易得多,而不是想知道你所暴露的整个命名空间中的错误来自哪里。

如果存在一系列命名空间或命名空间的名称太长,人们也会对单个函数/变量使用using指令。如果你有类似的东西

namespace my_really_long_and_pointless_namespace_that_does_nothing_at_all {
    void foo() { ... }
}

要么

namespace1 {
    namespace2 {
        ...
            namepaceN {
                void foo() { ... }
            }
    }
}

每次想要调用foo()方法时都必须编写整个内容,这是一种痛苦。通过写作

using my_really_long_and_pointless_namespace_that_does_nothing_at_all::foo;

和分别

using namespace1::namespace2:: ... ::namespaceN::foo;

你不用手指做一些工作。


1
投票

试着这样做:

namespace A { 
    void f() { // first function 
    } }

using A::f; // introduces only above function

namespace A { 

    void f(int) { // second function 
    } 
} 

0
投票

可以将它们包装在另一个范围内:

namespace B { // Wrap the first function
    void f() { A::f(); }
}

namespace C { // Wrap the second function
    void f(int i) { A::f(i); }
}

int main(int argc, char *argv[])
{
    {
        using B::f; // Make the first function available
        f();
    } // Make the first function unavailable

    {
        using C::f; // Make the second function available
        f(0);
    } // Make the second function unavailable

    return 0;
}

但我不认为你可以用一个using声明做到这一点。


0
投票

C ++没有从命名空间导入一个特定函数重载的机制。

作为一种解决方法,您可以将函数调用包装到本地函数中:

static inline void f(int i) { A::f(i); }

关键字static非常重要 -

  1. 它降低了当前编译单元对全局命名空间污染的风险
  2. 它可以在多个编译单元中执行此操作(因此可以放在头文件中)
  3. 它允许编译器忽略额外的函数调用(调用f()A::f()之间生成的代码没有区别)
  4. 如果从未调用f,则不会生成额外的代码
© www.soinside.com 2019 - 2024. All rights reserved.