5

このデモプログラムを検討してください。

#include <stdio.h>

class Base
{
public:
    virtual int f(int) =0;
    virtual int f(){ return f(0); }

    virtual ~Base(){ }
};

class Derived : public Base
{
public:
    int f(int i)
    {
        return (10 + i);
    }
};

int main(void)
{
    Derived obj;
    printf("%d\n", obj.f(1));  // This works, and returns 11
    printf("%d\n", obj.f());   // Adding this line gives me the error listed below
}

これにより、次のコンパイルエラーが発生します。

virtualfunc.cpp: In function ‘int main()’:
virtualfunc.cpp:25:26: error: no matching function for call to ‘Derived::f()’
virtualfunc.cpp:15:9: note: candidate is: virtual int Derived::f(int)

私の望みは、派生クラスがそれを定義していないので、obj.f()への呼び出しがへの呼び出しになり、それがクラスBaseの定義ごとにへの呼び出しになることでした。Base::obj.f()Derived::obj.f(0)

私はここで何が間違っているのですか?これを達成する方法はありますか?obj.f()具体的には、への呼び出しで10を返したいのですが。

(これを解決するためにデフォルトの引数を使用できることにも注意してください。ただし、このコードは私の問題の簡潔な例にすぎないため、デフォルトの引数を使用するように言わないでください。)

ありがとう。

4

3 に答える 3

8

発生している問題は、純粋仮想関数に直交しており、C++がクラス階層で名前解決を行う方法に関係しています。

あなたが書くとき

obj.f();

C ++は、f何を呼び出すかを認識できるように、という名前の関数を検索しようとします。objはタイプであるため、Derived内部で開始し、Derivedと呼ばれる関数を探しますf。最終的にはが見つかりDerived::f(int)、この関数は引数を取りますが、C ++はこれが呼び出そうとしているメソッドであると見なし、検索を停止します。次に、コンパイラーは、パラメーターなしでそれを呼び出そうとしていることに気づき、関数呼び出しに関するエラーを出します。

Base::f()これを修正するには、基本クラスに含まれている関数も検索する必要があることをC++コンパイラに通知する必要があります。これを行うにはDerived、次のように定義を変更できます。

class Derived : public Base
{
public:
    int f(int i)
    {
        return (10 + i);
    }

    using Base::f;
};

この行using Base::fは、C ++に、Basenamedfの関数をの一部であるかのように扱う必要があることを示していDerivedます。fこのように、コンパイラがという名前の関数を検索しようとすると、Derived::f(int)との両方が検出されBase::f()ます。Base::f()リストしたコードを使用して呼び出しようとしていることをコンパイラーが認識できるため、呼び出しは成功します。

お役に立てれば!

于 2011-06-03T22:07:12.327 に答える
3

f(int)派生クラスのの定義は、Base::fオーバーライドしなかった名前を非表示にします。あなたがする必要があるusing Base::f;のは、派生クラスに書くことによってこれを再表示することです:

class Derived : public Base
{
public:

    using Base::f;   //note this line!

    int f(int i)
    {
        return (10 + i);
    }
};
于 2011-06-03T22:08:20.377 に答える
3

その理由は、f(でDerived)定義されhidesf関数がBaseクラスからのものであるためです。解決策はを追加することusingです。このような:

class Derived : public Base
{
public:
    int f(int i)
    {
        return (10 + i);
    }

//  vvvvvvvvvvvvvv
    using Base::f;
};
于 2011-06-03T22:09:42.697 に答える