1
#include <list>
using std::list;
class foo { ...
class bar : public foo { ...
static void print_all(list<foo*> &L) { ...
list<foo*> LF;
list<bar*> LB;
...
print_all(LF); // works fine
print_all(LB); // static semantic error

コンパイラが2番目の呼び出しを許可しない理由を私は知っていると思います。コンパイラがこの種の呼び出しを受け入れた場合に発生する可能性のある悪いことの例を誰かが挙げられますか?

4

2 に答える 2

3

もちろん!print_allがこれを行う場合はどうなりますか?

L.push_back(new Foo);

これで、Barポインターのリストに、BarではないFooオブジェクトへのポインターが含まれます。次に、Fooクラスに存在しないBarのメソッドを呼び出そうとすると、メソッドがFooオブジェクトに存在しないため、実行時に重大な問題が発生します。

お役に立てれば!

于 2012-06-18T03:26:33.433 に答える
2

コードでは 2 つの異なる処理が行われていますが、その説明は異なります。最初の問題は、インスタンス化する型が関連している場合でも、テンプレートの異なるインスタンス化が無関係であることです。この特定のケースでは、 が のベースであっても、std::list<foo*>とは何の関係もありません。これは言語の設計の一部であり、何もできません。std::list<bar*>foobar

2 つ目の問題は、コンパイラが不満を言っているわけではありません。一般に、 のコンテナは のderivedコンテナとして参照によって使用できないということですbase。これは @templatetypedef が提起した問題ですが、繰り返しになりますが、これはコードの問題ではなく、別の例では次のようになります。

void f( base** p );
int main() {
   derived *d;
   f( &d );          // error
}

この場合の問題は、@templatetypedef が指摘しているように、非 const の方法でderivedポインター/コンテナーの代わりにポインター/コンテナーを使用すると、ポインターに非型を格納できるため、エラーが発生しやすいことです。/容器。base derived

于 2012-06-18T03:40:28.407 に答える