简体   繁体   English

成员函数隐藏自由函数

[英]member function hiding free function

void foo(int)
{
}

class X
{
    void foo()
    {
    }

    void bar()
    {
        foo(42);
        // error: no matching function for call to 'X::foo(int)'
        // note: candidate is:
        // note: void X::foo()
        // note:   candidate expects 0 arguments, 1 provided        
    }
};

Why is C++ unable to call the free function (which is the only one with the correct signature)? 为什么C ++无法调用free函数(这是唯一具有正确签名的函数)?

Because the two identifiers are defined in different scopes, and overload resolution only concerns about functions in the same scope. 因为这两个标识符是在不同的作用域中定义的,所以重载解析仅涉及同一作用域中的函数。 Once the compiler finds that the class has a foo , it stops climbing up to wider scopes (C++11 §3.4.1/1), so the free function foo is hidden. 一旦编译器发现该类具有foo ,它将停止爬升到更宽的范围(C ++ 11§3.4.1/ 1),因此自由函数foo被隐藏。

You need to use a qualified name to refer to the global foo : 您需要使用限定名称来引用全局foo

::foo(42);

The logical reason is Consistency . 逻辑原因是一致性

  • Suppose as per the suggestion, compiler resolves foo(42) to ::foo(int) . 假设按照建议,编译器将foo(42)解析为::foo(int)
  • Now after sometime, if you change X::foo() to X::foo(int) then foo(42) will be resolved to X::foo(int) . 现在过了一段时间,如果将X::foo()更改为X::foo(int)那么foo(42)将解析为X::foo(int) Which is not consistent. 哪个不一致。

That is the also the reason why derived class function hides base class function when there are similar names. 这也是当名称相似时派生类函数隐藏基类函数的原因。

Such cases can be resolved in 2 ways; 这种情况可以通过两种方式解决:

(1) Give fully qualified name (eg ::foo(42) ) (1)给出完全限定的名称(例如::foo(42)

(2) Use using utility; (2)使用实用程序using eg 例如

void bar()
{
  using ::foo;
  foo(42);
}

A name in an inner scope hides names in outer scopes. 内部作用域中的名称在外部作用域中隐藏名称。 It doesn't matter if it is a function or something else, or if you are in a class or a namespace. 它是函数还是其他东西,或者您是在类还是在名称空间中,都没有关系。

Only if the name lookup finds several functions with the same name will the overload resolution kick in to try to select the one that is the best match for the call. 仅当名称查找找到具有相同名称的多个函数时,过载解析才会起作用,以尝试选择最适合该调用的函数。

Really like your question. 真的很喜欢你的问题。 Also I could say, use this syntax: 我也可以说,使用以下语法:

::foo(42);

But I can say that in my opinion it's more elegant and good programming, set namespaces, so you can write something like this: 但是我可以说,我认为这是更优雅,更好的编程,可以设置名称空间,因此您可以编写如下内容:

namespace MyNameSpace
{
   void foo(int){}

   class X
   {
        void foo(){}

        void bar()
        {
            MyNameSpace::foo(42);
        }
   };
};

This is a good thing because Namespaces allow to group classes, objects and functions under a name. 这是一件好事,因为Namespaces允许将名称下的类,对象和函数分组。

PS: Then this help you to understand the meaning of write ::foo(42); PS:这样可以帮助您理解write ::foo(42);的含义::foo(42); when you haven't any namespace. 当您没有任何名称空间时。

I cannot answer the why part of your question -- I do not know what was the rationale behind that in the language spec. 我无法回答您的问题的部分原因-我不知道语言规范背后的原因是什么。

To call the global function in your example, use the :: syntax: 要在示例中调用全局函数,请使用::语法:

::foo(42);

The reason for this is the fact, that the compiler will look for a matching function name first, ignoring return values and parameters. 原因是这样的事实:编译器将首先查找匹配的函数名称,而忽略返回值和参数。 When inside a class, it will try to look for a matching member there (in fact, it will look through all scopes going "upwards"; local scope(s), function scope, class scope, namespace scope, global scope, etc.). 在类内部时,它将尝试在其中查找匹配的成员(实际上,它将遍历所有“向上”的作用域;本地作用域,函数作用域,类作用域,名称空间作用域,全局作用域等)。 )。

X::foo is the first matching name. X::foo是第一个匹配名称。 THEN (not before) it will try to pick the right overload (if there are multiple declarations) based on the parameters (which is the reason you can overload the same function with different parameters but not different return values only) and then it will check the return value (if there's any). 然后(不早于此)它将尝试根据参数选择正确的重载(如果有多个声明)(这是您可以使用不同的参数重载同一个函数,而不能仅返回不同的返回值的原因),然后它将检查返回值(如果有)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM