【问题标题】:C++ virtual method confusionC++虚方法混淆
【发布时间】:2013-03-01 16:04:27
【问题描述】:

我有一个关于继承和虚方法的基本 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”方法被声明为虚拟的。 我想知道为什么程序会这样。

提前致谢

【问题讨论】:

标签: c++ inheritance methods virtual


【解决方案1】:

您的向量包含A 对象:

vector<A> v;

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

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

这叫object slicing

【讨论】:

  • 啊,我明白了。我发现这种行为非常令人困惑,可能是因为我来自 Java 世界......
  • @SvenHager 对,这就是你的价值语义。在 Java 中,“对象”是一种指针/引用,向量的等价物将保存这些引用,因此存在动态调度的范围。在 C++ 中,您将存储指向基类的智能指针以实现相同的目的。
【解决方案2】:

您是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

【讨论】:

    【解决方案3】:

    b 被复制到A 的实例以插入vector 时,您必须使用vector&lt;A*&gt; 才能按预期工作。

    【讨论】:

      【解决方案4】:

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

      【讨论】:

      • 你可以使用 std::vector<:shared_ptr>> a;
      • 作为 AnatolyS,您可以使用共享指针来避免摆脱对象的麻烦(仅在动态分配的情况下!)或者您可以使用原始/“经典”指针,但请确保使用仅当指针指向 有效 对象时(例如不是在堆栈展开之后)
      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          猜你喜欢
          • 2012-09-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-12-30
          • 2011-09-19
          • 2018-04-20
          • 1970-01-01
          相关资源
          最近更新 更多