【发布时间】:2020-04-27 10:57:38
【问题描述】:
通过基类引用(没有虚拟operator=)分配派生对象时发生的对象切片是定义明确的操作吗?即,标准是否保证对象的派生部分不受影响?
这里和其他地方关于对象切片的许多问题,都给出了如下示例:
struct Base{
int x;
Base(int xx) :x(xx) {}
virtual void print() const {std::cout << "Base("<<x<<")\n";}
};
struct Derived : Base{
int y;
Derived(int xx, int yy ) :Base(xx),y(yy){}
void print() const {std::cout << "Derived("<<x<<","<<y<<")\n";}
};
int main()
{
Derived d1{1,2};
Derived d2{3,4};
Base& br = d1;
br = d2; // assign a Derived through a Base&
br.print(); // prints Derived(3,2)
}
该示例旨在表明,通过Base& 分配时,它仅分配Base 类成员,而保持Derived 中的成员不变。
使用-fsanitize=undefined 构建上述示例不会产生任何问题,它会在我运行过的所有系统上产生预期的输出。
问题是,标准是否保证了这一点?据我了解,因为Base::operator= 不能写在对象的Base 部分之外,并且对象的Derived 部分(此处为int y)不能与Base 部分有任何重叠。
我缺少一些极端情况吗? (当然,有很多不一致的对象会导致未定义的行为,但我的问题仅限于赋值操作期间发生的情况。)
【问题讨论】:
标签: c++ inheritance reference language-lawyer object-slicing