-1

基本クラス:

class Base
{
    public:
        virtual int f() const
        {
            return 1;
        }
};

派生クラス:

class Derived: public Base
{
    public:
        void f() const {}
};

上記のコードは、「戻り値の型が同一ではありません/共変エラー」をスローします。

私はそれに関するいくつかの議論を読みました。これは似ていますが、戻り値の型が同一/共変でない場合にコードが壊れるとだけ言っています。 戻り値の型が異なるメンバー関数をオーバーライドする

期待した動作が起こらないのはなぜですか?

予想される動作: Derived の VPTR は Base::f() を指します (仮想関数にオーバーライドが提供されていない場合に備えて読みました。Derived オブジェクトは継承されたクラス バージョンを使用するだけです)。また、名前 f() を非表示にするため、次のような呼び出しになります。

Derived x;
x.f();

Derived::f() と次のような呼び出しを呼び出す必要がありました。

x.Base::f();

Base::f() 関数を呼び出すべきでした。これはコードを壊しているようには見えません。アップキャストされた場合でも、両方のクラスの VPTR が同じ Base::f() を指しているため、コードを壊すべきではありません。

私が考えることができる唯一の理由は、そのような宣言 (同じ署名と共変/同一の戻り値の型) が仮想メソッドをオーバーライドするために予約されており、それを使用して期待どおりの動作を引き起こすことができないということです。

4

1 に答える 1

0

コンパイラは、一致するシグネチャ (引数、constness) を検出すると、void f() const宣言を自動的に virtual にします。したがって、 の定義Derivedは次のように解釈されます。

class Derived: public Base
{
    public:
        virtual void f() const {} // virtual keyword is added
};

明らかにオーバーライドしようとしているように見えますBase::f()。これはすべて、関数シグネチャがBaseandDerivedクラスで一致するために発生します。シグネチャが一致しなかった場合、これだけが再定義となり、その場合はBase::f()inDerivedクラスが非表示になります。

于 2021-06-07T03:43:57.727 に答える