使用声明对两个完全相同名称的名称查找的影响

effects of using declaration on name lookup for two exactly same names

基本上,我的问题与名称查找和 using 声明 (http://en.cppreference.com/w/cpp/language/namespace) 有关。
假设我们有以下(绝对愚蠢的)代码:

class Base { 
public:
    void fun()
    {std::cout << "Base fun" << std::endl;}
};

class Derived : public Base { 
public:
    // Here both names "fun" are visible or not?
    using Base::fun;//let's call this func_1

    void fun() //let's call this func_2
    {
        std::cout << "Derived fun" << std::endl;
    }
};

Derived d;
d.fun(); // This resolves to func_2, why?

因此,我的理解是现在我们应该两个 名字都可见,然后对于名字查找,应该有一些歧义。但实际上并非如此。是什么原因或者说是我理解错了一些概念?

标准对这种情况有特殊规定。

When a using-declaration brings names from a base class into a derived class scope, member functions and member function templates in the derived class override and/or hide member functions and member function templates with the same name, parameter-type-list (8.3.5), cv-qualification, and ref-qualifier (if any) in a base class (rather than conflicting).

([namespace.udecl]/15)

请注意,与往常一样,您可以通过执行 d.Base::fun().

强制调用 Base::fun

您所引用的 link 是针对 namespace 的,您应该引用 class using-declaration,其中指出:

If the derived class already has a member with the same name, parameter list, and qualifications, the derived class member hides or overrides (doesn't conflict with) the member that is introduced from the base class.

对于您发布的代码,Base 中的 void fun()Derived 中的 void fun() 隐藏,所以不,它们不是 [=37] =],除非你在调用 fun 时明确表示,例如:

class Base { 
    public:
        void fun() { std::cout << "base" << std::endl; }
};

class Derived : public Base { 
    public:
        using Base::fun;
        void fun() { std::cout << "derived" << std::endl; }
};

Derived d;
d.fun(); // name lookup calls Derived::fun
d.Base::fun(); // explicitly call Base::fun

此外,由于您已经公开派生自 Base,严格来说,您不需要 using 声明;如果 void fun()Base 中的 protected 或者你 private/protected'ly 继承自 Base,示例:

#include <iostream>

class Base {
    public:
        void fun() { std::cout << "base" << std::endl; }
    protected:
        void fun2() { std::cout << "base2" << std::endl; }
};

// class default is private
class Private : Base {
    public:
        // fun() won't be accessible since private inheritance and no using
        // fun2 can now be accessed directly
        using Base::fun2;
};

class Public : public Base {
    public:
        // fun is already public
        using Base::fun2; // bring into scope
};

class Derived : public Base {
    public:
        using Base::fun;
        using Base::fun2;

        // overriden method fun, no conflict, choose this method if type is Derived
        void fun() { std::cout << "derived" << std::endl; }
};

int main(int argc, char* argv[])
{
    Private p;
    Public u;
    Derived d;

    // generates a compiler error since Base is privately inherited
    //p.fun();
    p.fun2(); // OK, output: base2

    u.fun(); // OK, output: base
    u.fun2(); // OK, output: base2

    // use Derived::fun since override
    d.fun(); // OK, output: derived
    d.Base::fun(); // OK, output: base
    d.fun2(); // OK, output: base2

    return 0;
}

希望能帮到你