0

基本上,我的问题与名称查找和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?

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

4

2 回答 2

3

该标准对这种情况有一个特殊的规则。

using-declaration将基类中的名称带入派生类范围时,派生类中的成员函数和成员函数模板会覆盖和/或隐藏具有相同名称的成员函数和成员函数模板,parameter-type-list (8.3 .5)、cv-qualification 和ref-qualifier(如果有)在基类中(而不是冲突)。

([命名空间.udecl]/15)

请注意,像往常一样,您可以Base::fun通过 do 强制调用d.Base::fun()

于 2016-04-14T23:20:26.167 回答
0

您引用的链接是namespace's 的,您应该引用它声明的classusing-declaration

如果派生类已经有一个具有相同名称、参数列表和限定条件的成员,则派生类成员隐藏或覆盖(不冲突)从基类引入的成员。

在您发布的代码的情况下,void fun()inBase被 in 隐藏void fun()Derived所以不,它们不是“可见”的,除非您在调用时明确表示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声明;你会在那个或者你/ 'ly继承自的实例void fun()中,例如:protectedBaseprivateprotectedBase

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

希望能有所帮助

于 2016-04-14T23:24:09.850 回答