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が基底クラスの名前を派生クラスのスコープに持ち込む場合、派生クラスのメンバー関数とメンバー関数テンプレートは、同じ名前のパラメーター型リスト (8.3 .5)、cv-qualification、およびref-qualifier (存在する場合) を基底クラスに (競合するのではなく) 使用します。

([名前空間.udecl]/15)

いつものように、 を実行することで強制的Base::funに呼び出されることに注意してくださいd.Base::fun()

于 2016-04-14T23:20:26.167 に答える
0

参照しているリンクは のものです。namespace代わりに、次のように記述されているclassusing-declaration を参照する必要があります。

派生クラスに同じ名前、パラメーター リスト、および修飾子を持つメンバーが既にある場合、派生クラスのメンバーは、基本クラスから導入されたメンバーを非表示にするかオーバーライドします (競合しません)。

投稿されたコードの場合、void fun()inはinBaseによって隠されているため、呼び出すときに明示的に指定しない限り、どちらも「表示」されません。例:void fun()Derivedfun

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()あなたはprotectedBaseまたはあなたがprivate/protectedから継承したインスタンスで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;
}

それが役立つことを願っています

于 2016-04-14T23:24:09.850 に答える