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;

当你 push_back 一个对象到其中时,向量会将它的一部分B复制到一个新对象中。这相当于这样做:AA

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

b被分割成一个实例,A当它被复制以插入 时vector,您必须使用vector<A*>它才能按预期工作。

于 2013-03-13T15:56:21.410 回答
0

你应该有指针向量才能有多态行为:)

于 2013-03-13T15:54:15.250 回答
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

向量 v 包含 A 类型的对象。当您将对象推回 v 时,这些对象将使用 A 的复制构造函数进行实例化。就像您稍后在函数 f 上调用的每个对象实际上都是 A 类型并且永远不会执行B 的 f()。

于 2013-03-13T16:00:21.507 回答