C ++虚方法混淆

时间:2013-03-13 15:51:23

标签: c++ inheritance methods virtual

我有一个关于继承和虚方法的基本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

因为&#34; f&#34;方法声明为虚拟。 我想知道为什么程序会以这种方式运行。

提前致谢

6 个答案:

答案 0 :(得分:6)

您的矢量包含A个对象:

vector<A> v;

当您将B对象推入其中时,该向量会将其A部分复制到新的A对象中。这相当于这样做:

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

这称为object slicing

答案 1 :(得分:3)

您是slicing对象,您需要使用指针或references才能正常运行。使用指针的示例:

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

答案 2 :(得分:2)

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

答案 3 :(得分:0)

你应该有指针的向量,以便具有多态行为:)

答案 4 :(得分: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被销毁时(当它们超出范围时),这些指针将变为无效。

答案 5 :(得分:0)

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