1

継承と仮想メソッドに関する基本的な C++ の質問があります。

このコードを考慮してください:

#include <iostream>
#include <vector>
using namespace std;

class A {
public:
  virtual void f() {cout << "A\n";};
};

class B : public A {
public:
  void f() {cout << "B\n";};
};

int main() {
  A a;
  B b;
  vector<A> v;
  v.push_back(a);
  v.push_back(b);

  for (int i = 0; i < v.size(); ++i)
    v.at(i).f();
}

このコードを実行すると、出力されます

A
A

印刷されない理由がわかりません

A
B

「f」メソッドが仮想として宣言されているためです。プログラムがこのように動作する理由を知りたいです。

前もって感謝します

4

6 に答える 6

6

あなたのベクトルにはAオブジェクトが含まれています:

vector<A> v;

オブジェクトをプッシュバックするBと、ベクターはそのA一部を新しいAオブジェクトにコピーします。これは、次のことと同じです。

A a;
B b;
a = b;
a.f();

これはオブジェクトのスライスと呼ばれます。

于 2013-03-13T15:54:23.377 に答える
3

オブジェクトをスライスしています。これが適切に動作するには、ポインターまたは参照を使用する必要があります。ポインタを使用した例:

int main()
{
  vector<A*> v;
  v.push_back(new A);
  v.push_back(new B );

  for (int i = 0; i < v.size(); ++i)
    v[i]->f();
}

これにより、必要polymorphicな動作が得られ、次の出力が得られます。

A
B
于 2013-03-13T15:53:51.030 に答える
2

bAに挿入するためにコピーされたときに のインスタンスにスライスされます。これを期待どおりに機能させるvectorには、 を使用する必要があります。vector<A*>

于 2013-03-13T15:56:21.410 に答える
0

ベクトルvには、タイプAのオブジェクトが含まれています。オブジェクトをvにプッシュバックすると、これらのオブジェクトはAのコピーコンストラクターを使用してインスタンス化されます。同様に、関数fで後で呼び出す各オブジェクトは、実際にはタイプAであり、実行されません。 Bのf()。

于 2013-03-13T16:00:21.507 に答える
0

C++ では、オブジェクトへのポインターと参照のみがポリモーフィックに動作します。ベクターには、タイプ A の非ポリモーフィック オブジェクトが含まれています。

試す

int main() {
  A a;
  B b;
  vector<A*> v;
  v.push_back(&a);
  v.push_back(&b);

  for (int i = 0; i < v.size(); ++i)
    v.at(i)->f();

ただし、a と b が破棄されると (スコープ外になると)、これらのポインターは無効になることに注意する必要があります。

于 2013-03-13T15:58:26.890 に答える
0

ポリモーフィックな動作を行うには、ポインターのベクトルが必要です:)

于 2013-03-13T15:54:15.250 に答える