3

私たちが持っているとしましょう

class A {    
public:    
    virtual int foo() { cout << "foo!"; }    
}

class B : public A {
public:    
    virtual int foo() =0;
}

class C : public B {
public:
    virtual int foo() { cout << "moo!"; }
}

これは本当にオーバーライドですか?これは実際にはオーバーロードしていると思います。このようなものをデザイン的に作る意味は何ですか?

基本クラス A を取得しました。次に、具象クラス A から派生した抽象派生クラス B を取得し、C を介して B を実現しました。

私たちはここで何をしていて、意味がありますか?

4

4 に答える 4

3

オーバーロードとは、名前が同じでパラメーターが異なる 2 つの関数があることを意味します。ここではそうではありません。

例:

int functionA() { /*...*/ };
int functionA(int someParameter) { /*...*/ };

オーバーライドとは、サブクラスで同じパラメーターを使用して関数を書き換えることを意味します。それがあなたが例として提示したものです。

それが定義部分です。次に、設計に進みます。

純粋仮想関数がある場合、具象サブクラスはそれをオーバーライドする必要があります。したがって、純粋仮想関数を追加することで、すべてのサブクラスが同じ関数セット (= インターフェイス) を提供するようになります。これは、サンプル コードの場合のようです。

しかし、具象スーパークラスはすでに foo() のデフォルト機能を実装しているため、これはあまり良い例ではありません。サブクラス (および foo() の呼び出し元) は通常、デフォルトの実装にフォールバックできるはずなので、それを純粋に仮想的に再定義する抽象サブクラスがある場合、それはクラス階層に欠陥があることを示しています。このような抽象的な例で説明するのは少し難しいですが、このような階層は少し怪しいと思います。

于 2009-01-27T13:05:43.310 に答える
1

ここでの純粋仮想メソッドの唯一の効果は、B を抽象クラスにすることだと私には思えます。

于 2009-01-27T12:48:44.827 に答える
1

class のインスタンスへpの型のポインターがある場合でも、まだ呼び出しているため、オーバーライドしています。A*Cp->foo()C::foo()

おそらく、設計者は、具体的なクラスから派生した階層に抽象クラスを挿入し、サブクラスでメソッドのオーバーライドを強制したかったのでしょう。さほど賢明とは思えません。

于 2009-01-27T12:51:19.377 に答える
1

B から派生したクラスはint foo();を実装する必要があると言っています。. 他のプログラマーにfoo()をどのように動作させたいかを考えさせるために、このようなことをしたいかもしれませんが、それは悪い考えだと思います - 実際には、彼らはA::foo()を呼び出して実装する可能性があります。

Bを抽象化したいだけの場合は、純粋な仮想デストラクタを指定してください。ただし、リンク エラーを回避するために、デストラクタの実装も提供する必要があります。

于 2009-01-27T15:50:05.383 に答える