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

26

考虑以下的 C++ 代码。

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

    void f(int) { // second function
    }
}
...
using A::f; // introduces both functions
有没有一种方法只引入一个函数?

using 总是应用于标识符,而不是具体的实体名称。这就是事实。 - sbi
7个回答

21

该行为在标准中已经定义。

C++03 7.3.3 using声明:

"…如果名称是一个重载成员函数的名称,则所有被命名为该名称的函数都必须可访问。"


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);
}

演示

编辑: 更好的方法是将A::f(int)放在嵌套的namespace中,并引入别名(以便于使用)。

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

现在,其他函数也可以用作 A_::f(int)

你的演示有缺陷--你在声明之前调用了A::f(int),所以当然找不到它。这是一个修复版本:http://www.ideone.com/2weTx - TonyK
@iammilind: 尽管第二种方法是正确的做法,但第一种方法是错误的。采用那种方法将会是代码维护的噩梦。编写简单易懂的代码总是更好的选择,这样下一个接手它的人就能轻松理解。这样的技巧不适合实际应用。 - Alok Save

3
据我所知,目前没有这样的功能。如果这是一个问题,您可以编写一个包装函数来解决它。
void f(int i) { A::f(i); }

2
我将给出更多的例子作为其他回答的补充。
许多C++编程书籍通常会在源文件的某个位置添加以下代码行,以公开整个STD命名空间:
using namespace std;

暴露完整命名空间实际上在现实生活中是一种不好的做法,因为可能会发生各种冲突,特别是当许多开发人员都在同一个任务上工作时。这种编程风格也违反了面向对象编程的基本规则之一-通过封装数据避免暴露更多内容。这就是为什么类(例如)有公共和私有成员、getter和setter等。命名空间只是另一种分组信息的方式。暴露整个 std 命名空间违反了这个规则,特别是如果您只想使用 std::coutstd::cinstd::endl。您可以轻松地对特定函数应用 using,这样可以更精确地控制,并且更容易避免在可能使用多重命名空间时出现命名冲突:
using std::cout;
using std::cin;
using std::endl;

这使得您可以在代码中调用coutcinendl,而无需使用命名空间前缀。如果您在某个时刻遇到命名冲突,查看一组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,则不会生成额外的代码

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接