好了,它会一点一点技巧。这里是(简化)代码:呼唤的基地之一赋值操作符与C++多重继承的派生类的虚函数表
class A
{
virtual ~A();
// fields, none of which has an assignment operator or copy constructor
};
class B
{
virtual ~B();
// same as A
};
class Derived : public A, public B
{
Derived();
Derived(const B& b);
// no fields
};
随着Derived::Derived(const B& b)
(即接受它的一个基地)如下
Derived::Derived(const B& b)
{
*static_cast<B*>(this) = b;
// Do other stuff with protected fields declared in B
}
对我来说,这件事情在“只是避免做这样”线,但这是一个现有的代码,我们正在怀疑这个代码附近有可疑的内存损坏。所以,我很好奇,如果没关系。
好奇的部分这里是两个基类有虚函数表和他们都没有任何明确的复制/分配构造/运营商。
从我的理解,对于一个Derived
类的内存布局如下
`Derived`
---------
A-vtable
A-fields
B-vtable
B-fields
,当我调用虚函数,在“B”,宣布我使用B-vtable
,当我打电话一个虚拟函数,在“A”中声明,我使用的是A-vtable
,即vtables没有合并在一起。
而且从我的理解隐含的复制/赋值构造函数/运营商乙方应只影响B-fields
,当它被称为*static_cast<B*>(this) = b;
(static_cast
应该给一个指针开始的B-fields
,与B-vtable
居住在负从中偏移,据我所知) 。
所以,从我的理解,这个代码是完全安全的,正确的,虽然不清楚,哈克,但安全。我对么?是否有任何编译器特定的怪癖我应该知道(我们在这里讨论MSVC 2012)?
编辑:伙计们,我知道复制构造函数/赋值运算符的区别,非常感谢。这是发生在3次复制构造函数中的事件之一,因为我监督了它,现在每个答案都会花费一半的文本来告诉完全不相关的问题区别。
“经历了一个微妙的内存损坏可疑接近这个代码” - 去提取小例子呢! –
指针如'this'通常指向隐藏字段,其中V表指针被存储(即,对象的开始,不与偏移到它),因为它是用来相当频繁。指针是否来自静态投射是无关紧要的。我认为它也可能是负偏移,这可能是一个实现细节。 –