19

私には3つの異なる基本クラスがあります。

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

class BaseB
{
public:
    virtual int foo() { return 42; }
};

class BaseC
{
public:
    int foo() { return 42; }
};

次に、次のようなベースから派生します(A、B、またはCの代わりにXを使用します)。

class Child : public BaseX
{
public:
    int foo() { return 42; }
};

3つの異なる基本クラスで関数はどのようにオーバーライドされますか?次の3つの仮定は正しいですか?他に注意点はありますか?

  • BaseAでは、子クラスはコンパイルされず、純粋仮想関数は定義されません。
  • BaseBでは、BaseB*またはChild*でfooを呼び出すときに、子の関数が呼び出されます。
  • BaseCでは、Child *でfooを呼び出すときに子の関数が呼び出されますが、BaseB *では呼び出されません(親クラスの関数が呼び出されます)。
4

6 に答える 6

16

覚えておくべき重要なルールは、関数が仮想として宣言されると、派生クラス内の一致するシグネチャを持つ関数は常に仮想であるということです。そのため、Child of A と Child of B に対してオーバーライドされ、同じように動作します (BaseA を直接インスタンス化できないことを除いて)。

ただし、C では、関数はオーバーライドされませんが、オーバーロードされます。その状況では、静的型のみが重要です。オブジェクトが実際に何であるか (動的型) ではなく、それがポインターであるもの (静的型) で呼び出します。

于 2009-06-22T15:10:00.087 に答える
14

派生クラスでは、派生クラスのメソッドでキーワード virtual が使用されていなくても、基本クラスで virtual と定義されている場合、そのメソッドは virtual です。

  • を使用BaseAすると、意図したとおりにコンパイルおよび実行され、foo()仮想化され、クラスで実行されChildます。
  • と同様に、 virtual() であり、 class で実行さBaseBれるため、意図したとおりにコンパイルおよび実行されます。foo()Child
  • BaseCただし、コンパイルして実行しますが、 のコンテキストから呼び出すとバージョンが実行されBaseC、 のコンテキストで呼び出すとバージョンが実行されます。BaseCChildChild
于 2009-06-22T15:11:51.893 に答える
2

BaseA では、子クラスはコンパイルされず、純粋仮想関数は定義されません。

これは、BaseA のオブジェクトを作成しようとした場合にのみ当てはまります。Child のオブジェクトを作成し、BaseA* または Child* のいずれかを使用して foo() を呼び出すことができる場合

BaseB では、BaseB* または Child* で foo を呼び出すと、子の関数が呼び出されます。

オブジェクトは BaseB または Child のいずれかになるため、オブジェクトのタイプによって異なります。オブジェクトが BaseB の場合、BaseB::foo が呼び出されます。

BaseC では、Child* で foo を呼び出すときに子の関数が呼び出されますが、BaseB* では呼び出されません (親クラスの関数が呼び出されます)。

はい、しかしあなたは決してこれをしたくありません。

于 2009-06-22T15:13:41.093 に答える
2

ポリモーフィズムの観点からは、A を優先します。これにより、各子が仮想関数の独自の実装を持っていることがわかります。
有効なデフォルト実装がある場合は主に B を選択しますが、必要に応じてすべての子クラスに独自の実装があることを確認する必要があります。C はポリモーフィズムではないため、慎重に使用してください。

于 2009-06-22T15:23:09.657 に答える
1

それは主にあなたがそれをどのように呼んだかに依存します。

あなたがした場合:

class Child : public BaseA
{
public:
    int foo() { return 42; }
};

そしてやった

BaseA baseA = new Child();
baseA->foo();

Child の foo 関数を呼び出します。

ただし、これを行った場合:

BaseA baseA = new BaseA();

コンパイル時エラーが発生します。

于 2009-06-22T15:46:09.610 に答える
0

クラス Child、A から派生した場合にコンパイルされます。その型のオブジェクトをインスタンス化することはできません。

これは、Base からいくつかの関数をオーバーライドしてから再度派生させる場合に役立つ可能性があります。

于 2009-06-22T15:12:38.727 に答える