31

デフォルト引数を持つ純粋仮想メソッドを持つ抽象基本クラスを作成しました。

class Base {
    ...
    virtual someMethod(const SomeStruct& t = 0) = 0;
    ...
}

class Derived : public Base {
    ...
    virtual someMethod(const SomeStruct& t = 0);
    ...
}

それで、デフォルトの引数を純粋な仮想メソッドに設定し、全体を仮想メソッドに設定するのは良い習慣ですか?

4

5 に答える 5

39

実際、あなたのコードは、継承とポリモーフィック動作の両方を伴うため、デフォルト パラメータの最悪の使用パターンの 1 つです。関連する Scott Meyers のヒントを参照するようにというアドバイスを支持しますが、ここに簡単な概要を示します。

ポリモーフィック呼び出しの場合、動的型ではなく静的型の宣言に従って、デフォルトのパラメーターが使用されます。ランタイムはデフォルトのパラメーターを認識しないため、これは論理的ですが、ポリモーフィックな動作に関する適切な仮定を破ります。例えば、

#include <cstdio>

class Base
{
        public:
                virtual void f(int a = 1)
                {
                        printf("Base::f(%d)\n", a);
                }
};

class Deriv : public Base
{
        public:
                virtual void f(int a = 2)
                {
                        printf("Deriv::f(%d)\n", a);
                }
};

int main()
{
        Base* a = new Deriv();
        a->f();
        delete a;
        return 0;
}

収量:

Deriv::f(1)
于 2012-08-27T10:18:56.813 に答える
22

あなたのように、デフォルトのパラメーターと仮想関数の両方を使用したいことがよくあります。しかし、これはあいまいさにつながり、一般的には良い考えではないことを他の人が正しく指摘しています。私が使用している、かなり単純な解決策があります。仮想関数に別の名前を付けて保護し、パブリック関数にそれを呼び出す既定のパラメーターを指定します。

class Base {
protected:
    virtual void vSomeMethod(const SomeStruct& t ) = 0;
public:
    void someMethod( const SomeStruc& t = 0 )
    { vSomeMethod( t ); }
}

派生クラスは単にオーバーライドするだけvSomeMethodで、デフォルトのパラメーターについてはまったく気にしません。

于 2012-08-27T10:24:34.353 に答える
6

可能であれば、デフォルトのパラメーターをまったく使用しないでください

Scott Meyers によるEffective C++ の本を両方購入してください。後悔することはありません。

于 2012-08-27T10:03:08.360 に答える
0

私は...するだろう:

  • パラメーターを使用して仮想関数を定義します (デフォルト値なし)
  • 正しいデフォルト パラメータを渡す仮想関数を呼び出す非仮想関数を、パラメータをまったく指定せずに基本クラスに定義します。

このようにして、派生クラスはデフォルト値をまったく気にする必要がありません。

于 2012-08-27T10:26:31.520 に答える
0

このコードを意味のあるものにしたい場合:

Base* p = new Derived;
p->someMethod();

の静的型でpあるBase*ため、呼び出し時に使用されるベース署名です。デフォルト値が割り当てられ、仮想関数であるため、呼び出しは Derived にリダイレクトされます。

Derived::someMethod が...Base*ではなく別の値を受け取るようにする場合は、別の方法で定義することもできます。Derived*

重要なことは、これらの「関係」を十分に文書化することです。ほとんどのプログラマーは、コードを単純に読んだだけでは理解できないからです。

もちろん、特定のコンテキストに適していない場合は、他よりも多くの混乱を引き起こします。仮想関数のデフォルトのパラメーターを避け、ヘルパーの非仮想パラメーターを使用して適切に呼び出します。

しかし、読者の観点からすると、デフォルトのパラメーターは、読み取り不可能なパラメーターのリワークを使用して別のパラメーターを非公開で呼び出すオーバーロード関数よりも説明的です。

于 2012-08-27T11:35:51.523 に答える