2


2

メソッドがC ++の既存の仮想メソッドをオーバーライドしていることを確認する方法は?

仮想メソッドを持つ基本クラスがあるとしましょう:

class BaseClass
{
    virtual void MethodToOverride() const
    {
        DoSomething();
    }
};

そして、メソッドをオーバーライドする派生クラス(状況に応じて、再び仮想化できるかどうか):

class DerivedClass : public BaseClass
{
    void MethodToOverride() const
    {
        DoSomethingElse();
    }
}

たとえば、MethodToOverride non constを定義したり、間違った文字を使用して定義したりするなど、間違えた場合は、次のように新しいメソッドを定義するだけです。

void MethodToOverride() {} // I forgot the const
void MthodToOverride() const {} // I made a typo

したがって、これは正常にコンパイルされますが、実行時に望ましくない動作を引き起こします。

既存の関数の明示的なオーバーライドとして関数を定義する方法はありますか?そのため、間違って定義するとコンパイラは警告を表示しますか? 次のようなもの(存在しないことを知っています):

void MethodToOverride() const overrides BaseClass::MethodToOverride() const {}

5 Answer


6


最善の方法は、メソッドを `BaseClass`で純粋仮想と宣言することです。

class BaseClass
{
    virtual void MethodToOverride() const = 0;
};

実装するクラスが再び継承される場合(これは半良い方法として問題になります)、正しい実装を制御する方法はありません。


5


``属性。 ただし、http://en.wikipedia.org/wiki/C%2B%2B0x#Explicit_virtual_function_overrides [C ++ 0x]の一部です。

gccを使用している場合は、http://gcc.gnu.org/onlinedocs/gcc-4.4.5/gcc/C_002b_002b-Dialect-Options.html#index-Woverloaded_002dvirtual-177 [-Woverloaded-virtual]コマンドラインオプションを検討してください。 。


1


C 0xはこのための属性を提供します(vitautの答えを参照)。 Visual C は言語拡張機能を提供します。

しかし、ポータブルC ++ 98でできる最善のことは、サニティチェックです。基本クラスは、次のような同じ引数を受け入れるアクセス可能なメンバー関数を提供します。

// The following macro is mainly comment-like, but performs such checking as it can.
#define IS_OVERRIDE_OF( memberSpec, args ) \
    suppressUnusedWarning( sizeof( (memberSpec args, 0) ) )

どこで

template< typename T >
inline void suppressUnusedWarning( T const& ) {}

関数の実際の引数を使用して、オーバーライド実装でマクロを呼び出します。

*編集*呼び出し例の追加(免責事項:コンパイラーの手で触れられない):

class BaseClass
{
protected:
    virtual void MethodToOverride() const
    {
        DoSomething();
    }
};

class DerivedClass : public BaseClass
{
protected:
    void MethodToOverride() const
    {
        IS_OVERRIDE_OF( BaseClass::MethodToOverride, () );
        DoSomethingElse();
    }
};

このような健全性チェックを使用すると、特定のケースでコードの明瞭さが向上し、特定のケースでお尻を節約できます。 3つのコストがあります。 (1)他の誰かが、単なる有益なコメントや部分的なチェックではなく、保証と誤解する可能性があります。 (2)メンバー関数は、例にあるように、基本クラスではプライベートにすることはできません(ただし、おそらく肯定的です)。 (3)一部の人々は、マクロの使用に対して本能的に否定的に反応します(彼らはそれを理解せずに悪に関するルールを記憶しただけです)。

乾杯


0


基本クラスが抽象クラスである場合、解決策は、オーバーライドしたいメソッドを純粋仮想にすることです。 この場合、派生クラスをインスタンス化しようとすると、コンパイラは叫ぶでしょう。 純粋仮想関数にも定義を含めることができることに注意してください。

E.g.

class BaseClass
{
    virtual void MethodToOverride() const = 0;
    //let's not forget the destructor should be virtual as well!
};

inline void BaseClass::MethodToVerride const()
{
    DoSomething();
}
//note that according to the current standard, for some inexplicable reasons the definition
//of a pure virtual function cannot appear 'inline' in the class, only outside

基本クラスを抽象化する余裕がない場合、C 03は実行することはほとんどなく、@ vitautの答えはC 0xに必要なものを提供します。

あなたの質問に私を驚かせた文章がありました。 メソッドをさらに仮想化するかどうかを選択できると言います。 さて、C ++ 03ではできません。 メソッドが仮想として宣言されている場合、明示的に指定するかどうかにかかわらず、階層全体で仮想になります。 E.G.

class A
{
    virtual void f(){}
} ;
class B: public A
{
   void f(); //same as virtual void f();
};


0


これを試すことができます::)

#include

using namespace std;

class Base
{
    public:
        virtual void YourMethod(int) const = 0;
};

class Intermediate : private Base
{
    public:
        virtual void YourMethod(int i) const
        {
            cout << "Calling from Intermediate : " << i << "\n";
        }
};

class Derived : public Intermediate, private Base
{
    public:
        void YourMethod(int i) const
        {
            //Default implementation
            Intermediate::YourMethod(i);

            cout << "Calling from Derived : " << i << "\n";
        }
};

int main()
{
    Intermediate* pInterface = new Derived;
    pInterface->YourMethod(10);
}

コードはそれ自体を物語っていると思います。 「ベース」は、正しいシグネチャで関数を実装することを確認します(副作用として、デフォルトの動作を使用できる場合でも、常に実装します)が、インターフェースである「中間」は、デフォルトの実装があることを確認します。 ただし、警告が表示されます:)。