C 中的向量和多态性:对象切片揭秘
在处理 C 中的继承层次结构向量时,可能会遇到一些微妙的复杂情况妨碍预期的行为。考虑以下示例:
<code class="cpp">class Instruction { public: virtual void execute() { } }; class Add: public Instruction { private: int a; int b; int c; public: Add(int x, int y, int z) {a=x;b=y;c=z;} void execute() { a = b + c; } };</code>
现在,想象将 Add 对象存储在基类指针的向量中:
<code class="cpp">void some_method() { vector<Instruction*> v; Instruction* i = new Add(1,2,3) v.push_back(i); }</code>
稍后,在一个单独的方法中,我们尝试调用对向量的最后一个元素执行函数:
<code class="cpp">void some_other_method() { Instruction ins = v.back(); ins.execute(); }</code>
一个常见的误解是,execute 函数的行为就像在 Add 对象上调用一样。然而,事实并非如此。
问题源于向量存储值的方式:它们存储对象的副本,而不是引用。因此,当将 Add 对象推入向量时,它会被复制,从而产生指令类型的对象,从而丢失特定于 Add 的数据和方法。这称为对象切片。
为了避免对象切片,我们需要修改向量以保存引用而不是副本:
<code class="cpp">vector<Instruction*> ins</code>
或者,我们可以使用 std::reference_wrapper:
<code class="cpp">vector< std::reference_wrapper<Instruction> > ins</code>
通过使用引用,我们在向量中保留对象的原始类型,从而允许预期的多态行为。
以上是在 C 中使用继承层次结构向量时如何避免对象切片?的详细内容。更多信息请关注PHP中文网其他相关文章!