【问题标题】:Misunderstood the virtual functions work in vector误解了虚函数在向量中的作用
【发布时间】:2013-05-13 12:43:28
【问题描述】:

我在 c++ 上有以下代码:

#include <iostream>;
#include <vector>;

class A
{
public:
    A(int n = 0) : m_n(n) { }

public:
    virtual int value() const { return m_n; }
    virtual ~A() { }

protected:
    int m_n;
};

class B
    : public A
{
public:
    B(int n = 0) : A(n) { }

public:
    virtual int value() const { return m_n + 1; }
};

int main()
{
    const A a(1);
    const B b(3);
    const A *x[2] = { &a, &b };
    typedef std::vector<A> V;
    V y;
    y.push_back(a);
    y.push_back(b);
    V::const_iterator i = y.begin();

    std::cout << x[0]->value() << x[1]->value()
        << i->value() << (i + 1)->value() << std::endl;

    system("PAUSE");

    return 0;
}

编译器返回结果:1413.

我有点困惑,因为我认为正确的结果应该是 1414(作为虚拟函数)。你如何解释这个程序行为?

【问题讨论】:

  • 不要将; 放在#include 指令的末尾。
  • @Fabien 我对编译好的程序感到惊讶。

标签: c++ inheritance vector


【解决方案1】:

您是slicing 对象,为了获得多态性,您需要使用pointerreference。此示例尽可能接近您的原始示例并使用pointer 将按照您的意愿行事:

const A a(1);
const B b(3);

typedef std::vector<const A*> V;
V y;
y.push_back(&a);
y.push_back(&b);
V::iterator i = y.begin();

std::cout << (*i)->value()  << std::endl ;
++i ;
std::cout << (*i)->value()  << std::endl ;

【讨论】:

    【解决方案2】:

    在这里简要展示对象切片的工作原理:

    const A a(1);
    const B b(3);
    std::vector<A> y; // so y contains objects of type A
    
    y.push_back(a);   // y[0] is copy-constructed from a
    y.push_back(b);   // y[1] is copy-constructed from b
    

    请注意,在两个 push_back 调用中,始终通过自动生成的 A::A(const A&amp;) 复制构造函数构造 A

    还要注意 B is-a A,也就是说 b 可以隐式转换为 A 并传递给同一个复制构造函数。

    所以,y[1]A 的一个实例,其 m_n 值从 b 复制而来,但它的虚函数仍然是 A::value。如果你有构造函数B::B在初始化时修改值,而不是在返回时,你会看到你期望的结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-04
      • 1970-01-01
      • 2019-06-07
      • 1970-01-01
      • 2014-08-12
      • 2012-06-03
      • 1970-01-01
      • 2022-12-05
      相关资源
      最近更新 更多