我在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(作为虚函数)。你如何解释这个程序行为?
答案 0 :(得分:6)
您是slicing对象,为了获得多态性,您需要使用pointer
或reference
。此示例尽可能与原始示例保持一致并使用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 ;
答案 1 :(得分:4)
简要说明对象切片的工作原理:
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::A(const A&)
。
另请注意,B
是-a A
,也就是说b
可以隐式转换为A
并传递进入同一个拷贝构造函数。
因此,y[1]
是A
的一个实例,m_n
值从b
复制,但其虚函数仍为A::value
。如果你有构造函数B::B
在初始化时修改它,而不是在返回它时,你会看到你期望的结果。