5

戻り値の型は関数のオーバーライドに影響しますか? (私が知る限り、return typde は関数/メソッド シグネチャの一部ではありません) 基本クラスには、引数を取得せず、戻りint、純粋な仮想である関数があります。各派生クラスで、戻り値の型の列挙型を定義します。関数は派生クラスでオーバーライドされます。つまり、シグネチャは同じですが動作が異なります。問題は次のとおりです。オーバーライドは合法であり、戻り値の型は関数のオーバーライドの一部ではありませんか?

コード例:

class Base
{
  public:
  typedef int ret;
  virtual ret method() = 0;
};

class Der1
{
public:
  enum ret1{
    ret1_0,
    ret1_1
  };
  ret1 method() { return ret1_1;}
};

class Der1
{
public:
  enum ret2{
    ret2_0,
    ret2_1
  };
  ret1 method() { return ret2_0;}
};
4

4 に答える 4

5

さまざまな戻り値の型で関数をオーバーライドできますが、共変の戻り値の型のみが許可されます。

関数のオーバーライドとは、ポインターが指す実際のオブジェクトに応じて、基本クラスのメソッドまたは派生クラスのメソッドのいずれかが実行時に呼び出されることを意味します。
つまり
、基本クラス メソッドを呼び出すことができるすべての場所は、呼び出し元のコードを変更することなく、派生クラス メソッドの呼び出しに置き換えることができます。

これを達成するために可能な唯一の方法は、オーバーライドする仮想メソッドの戻り値の型を制限して、基本クラスと同じ型またはそれから派生した型 (共変の戻り値の型) を返すことであり、標準はこの条件を強制します。

この条件がなければ、既存のコードは新しい機能 (新しいオーバーライド関数) の追加によって壊れます。

于 2013-02-25T09:58:26.470 に答える
4

短い答え: いいえ、これは許可されていません。つまり、オーバーライドではなく上書きBase::method()しています。つまり、オーバーライドしているのではなく、同じ名前の新しいメソッドを作成しています。ほとんどのコンパイラは、それについて警告します。サンプルコードでは、純粋な仮想でBase::methodないことを前提として、次のことを考慮してください。

void callMethod(Base const& b)
{
  auto a1 = b.method();  //what should the type of a1 be? -> it's int. Every time.
  std::cout << a1 << '\n';
}

int main()
{
  Der1 d1;
  auto a2 = d1.method(); //a2 is ret1_1 of type ret1
  callMethod(d1);        //calls Base::method and prints that int, not Der1::method
}

戻り値の型が関数シグネチャの一部ではないことは間違いありません。しかし、仮想関数をオーバーライドする場合、重要なのは署名だけではありません。§10.3,7は明示的に次のように述べています。

オーバーライド関数の戻り値の型は、オーバーライドされた関数の戻り値の型と同じか、関数のクラスと共変でなければなりません。関数が関数をD::fオーバーライドする B::f場合、次の基準を満たす場合、関数の戻り値の型は共変です。

— どちらもクラスへのポインタ、両方がクラスへの左辺値参照、または両方がクラスへの右辺値参照

— の戻り値の型のクラスは、 の戻り値の型のB::fクラスと同じクラスであるD::fか、または の戻り値の型のクラスの明確でアクセス可能な直接または間接基本クラスです。D::f

— ポインターまたは参照の両方が同じ cv-qualification をD::f持ち、 の戻り値の型のクラス型は、 の戻り値の型のクラス型と同じ cv-修飾か、cv-修飾が少ないB::f

于 2013-02-25T10:04:15.070 に答える
1

あなたが持っているものはオーバーライドではありません。

c++ は、生のポインターと生の参照の共変の戻り値の型をサポートしています。

しかしそれだけです。

于 2013-02-25T10:00:58.267 に答える
1

基本クラスの関数の戻り値の型をオーバーライドして変更しないでください。基本メンバーを別のメンバーで非表示にして戻り値の型を変更することはお勧めしません。これは、ポリモーフィックな方法で使用できない奇妙な結果になるためです。

于 2013-02-25T10:03:11.323 に答える