2

$10.3/5

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

— どちらもクラスへのポインタまたはクラスへの参照です98)

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

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

struct A{};
struct B : A{};

struct X{
    virtual const A * const f(){return 0;}
};

struct Y : X{
    virtual const B * volatile f(){return 0;}
};

int main(){
    Y b;
    X &r = b;
    r.f();
}

上記の実験的なコードを書いたところ、コモーのエラー/警告が矛盾していることがわかりました。9 行目の警告は、戻り値の型の cv 修飾子が無意味であることを示しているようです。そして、まさにこの理由が、コードの形式が正しくないことにつながります。

"ComeauTest.c", line 5: warning: type qualifier on return type is meaningless
virtual const A * const f(){return 0;}
                  ^

"ComeauTest.c", line 9: warning: type qualifier on return type is meaningless
virtual const B * volatile f(){return 0;}
                  ^

"ComeauTest.c", line 9: error: return type is not identical to nor covariant with
      return type "const A *const" of overridden virtual function function
      "X::f"
virtual const B * volatile f(){return 0;}
                           ^

問題は、コモーが 9 行目で「警告」メッセージを出すのは正しいかということです。私はそれが実装で定義された動作であることを知っています.Comeauは単に親切にしようとしています. しかし、この場合、せいぜい紛らわしいです。

4

1 に答える 1

2

5 行目と 9 行目の「戻り値の型の型修飾子は無意味です」という警告は、非クラス型の右辺値が cv 修飾されないためです。

値によって返される関数の結果は右辺値であり、ポインターは非クラス型であるため、戻り値の型がそうであると述べていても、返されるポインターは cv 修飾されていません。

この警告は、共分散とは関係ありません。次の関数は、同じ警告を引き起こします。

int* volatile f() { return 0; }

10.3/5 の引用テキストについては、次のとおりです。

ポインターまたは参照の両方が同じ cv-qualification を持っている

これは、戻り値の型 (つまりvolatilein const int* volatile) の最上位の修飾を参照しています。トップレベルの修飾は無意味です、関数の型に影響を与えるため、上記の宣言を考えるとf、このスニペットは正しくありません。

int* (*q)() = f; // error:  can't convert int* volatile (*)() to int* (*)()

同様に、派生クラスのメンバー関数の戻り値の型の最上位の cv 修飾が基本クラスの戻り値の型の最上位の cv 修飾と一致しない場合、派生クラスのメンバー関数は基本クラスをオーバーライドしません。メンバー関数。

の戻り値の型のクラス型の cv-qualification が、 の戻り値の型のクラス型D::fと同じか、cv-qualification が少ないB::f

これは、戻り値のクラス型 (つまりconstin const int* volatile) の修飾を参照しています。この規則は、派生クラス メンバー関数の戻り値の型の修飾が、それがオーバーライドする基本クラス メンバー関数の戻り値の型の修飾と同じかそれ以下でなければならないことを意味します。

于 2010-08-29T05:16:42.487 に答える