class B {};
class D: public B {};
void foo(B b);
int main()
{
D d;
foo(d);
return 0;
}
这种情况下, D在装B, 发生对象切片, "切"字用在这里有一个不当的误导, 就是D中B的部分, 被切走之后就不存在了, 实际上, 逻辑上D中那个隐含的B部分, 应该保持不变, 但是, 编译器实现这种对象切片的方式, 却有可能破坏D中的那个B的状态. 需要这种切片时, 编译器会将D视为一个B对象, 然后由一个B对象构造另一个在栈上的B对象, 供函数foo使用, 这里会调用copy ctor函数, 如果B和D这样定义:
class B {
private:
int i_;
public:
B(): i_(1) {}
B(B & other) {
this->i_ = other.i_;
other.i_ = 0;
printf("addr: %p\n", &other);
}
void print() {
printf("i = %d, %s\n", i_, __FUNCTION__ );
}
};
class D: public B {
private:
int d_;
};
void foo(B b)
{
b.print();
}
int main()
{
D d;
printf("addr: %p\n", &d);
d.print();
foo(d);
d.print();
return 0;
}
则B(B &other)的实现会改变到原始的D对象. 最后一个d.print将显示值0.
标准的copy ctor应该是 B (const B &other)这种形式, 但编译器也同样视B( B &other)为合法的形式, 考虑auto_ptr这种特殊类的实现, 需要转移指针的控制权时, 就需要这种用法.
看来, 切片是有潜在危险的, 应该尽量避免.
阅读(969) | 评论(0) | 转发(0) |