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

发布于 2024-11-29 12:31:38 字数 211 浏览 2 评论 0原文

考虑以下 C++ 代码。

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

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

有没有办法只引入一个函数?

consider the following C++ code.

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

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

Is there a way to introduce only one function?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

箜明 2024-12-06 12:31:38

标准中明确定义了该行为。

C++03 7.3.3 using 声明

“...如果名称是重载成员函数的名称,则所有指定的函数都应可访问。”。

That behavior is well-defined in the Standard.

C++03 7.3.3 The using declaration:

"...If the name is that of an overloaded member function, then all functions named shall be accessible.".

御弟哥哥 2024-12-06 12:31:38

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)放入嵌套的namesapce中并引入别名(为了便于使用)。

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

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

using keyword will bring all the names into the current scope. So with this current code it's not possible.

However, you can introduce the names partially to the file as following:

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.

Edit:
The better way is to put A::f(int) inside a nested namesapce and introduce an alias (for ease of use).

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

Now, other function is also usable as A_::f(int).

汐鸠 2024-12-06 12:31:38

据我所知还没有。如果有问题,您可以编写一个包装函数。

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

Not as far as I know. You could write a wrapper function if it is a problem.

void f(int i) { A::f(i); }
来日方长 2024-12-06 12:31:38

除了其余答案之外,我还会举一些更多的例子。

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

using namespace std;

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

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

这允许您调用 <代码中的strong>cout、cinendl 不带命名空间前缀。如果您在某个时候遇到命名冲突,那么查看一组 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;

您可以节省手指的一些工作。

I will give some more examples in addition to the rest of the answers.

Many books for programming in C++ often expose the whole STD namespace by adding the following line somewhere at the beginning of a source file:

using namespace std;

Exposing the complete namespace actually happens to be a bad practice in real life due to various conflicts that may occur at some point especially when code is supplied by many developers that are working on the same task. Such programming style is also against one of the basic rules of object oriented programming - avoid exposing more than it is actually necessary by encapsulating your data. That is why classes for example have public and private members, getters and setters and so on. Namespaces are just another way to group information. Exposing the whole std namespace is against this rule especially if you want to be using let's say only std::cout, std::cin and std::endl. You can easily apply using to specific functions, which allows you a more precise control and a higher chance of avoiding naming conflicts in the multiple namespaces that you might be using at some point:

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

This allows you to call cout, cin and endl in your code without the namespace-prefix. If you get a naming conflict at some point it is much, much easier to look at a set of using-directives instead of wondering where in the whole namespace that you have exposed the error comes from.

People also use the using directive for a single function/variable if there is a chain of namespaces or the namespace's name is just too long. If you have something like

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

or

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

it is a pain in the butt to have to write the whole thing every time you want to call the foo() method. By writing

using my_really_long_and_pointless_namespace_that_does_nothing_at_all::foo;

and respectively

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

you spare your fingers some work.

无需解释 2024-12-06 12:31:38

尝试这样做:

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

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

namespace A { 

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

Try doing this:

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

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

namespace A { 

    void f(int) { // second function 
    } 
} 
旧梦荧光笔 2024-12-06 12:31:38

可以将它们包装在另一个作用域中:

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 声明来做到这一点。

It's possible to wrap them in another scope:

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

But I don't think you can do that with a single using declaration.

那请放手 2024-12-06 12:31:38

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

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

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

关键字static非常重要 -

  1. 它降低了当前编译单元的全局名称空间污染的风险
  2. 它使得可以在多个中执行此操作编译单元(因此可以放入头文件中)
  3. 它允许编译器省略额外的函数调用(调用 f()A 之间生成的代码没有区别: :f())
  4. 如果 f 是从未被调用,不会生成额外的代码

C++ has no mechanism to import one specific function overload from a namespace.

As a workaround you can wrap a function call into a local function:

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

The keyword static is very important -

  1. It reduces the risk of global namespace pollution to the current compilation unit
  2. It makes it possible to do this in multiple compilation units (and hence can be put in a header file)
  3. It allows the compiler to elide the extra function call (there will be no difference in generated code between calling f() and A::f())
  4. If f is never called, no extra code will be generated
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文