我不确定这是否是visual-c ++编译器中的错误或未定义的行为。
struct DummyBase { virtual ~DummyBase() = default; };
struct DummyDerived : virtual public DummyBase {};
只使用虚拟继承的类和派生类
DummyDerived derived;
DummyBase* base = &derived;
std::cout << "Derived : " << &derived << std::endl;
std::cout << "Base : " << base << std::endl;
将DummyDerived*
强制转换为DummyBase*
时,指针会偏移。这似乎是由虚拟继承引起的:
Derived : 00000000002CF838
Base : 00000000002CF840
即使指针值不同,比较也会返回true:
std::cout << "IsSame : " << (base == &derived) << std::endl << std::endl;
输出:
IsSame : 1
到目前为止一切顺利。
问题出现在以下设置中:
struct IBaseReturner
{
virtual DummyBase* Get() = 0;
};
struct IDerivedReturner : public virtual IBaseReturner
{
virtual DummyDerived* Get() = 0;
};
struct BaseReturner : public virtual IBaseReturner
{
};
struct DerivedReturner : public BaseReturner, public virtual IDerivedReturner
{
DummyDerived* Ptr;
virtual DummyDerived* Get() override { return Ptr; }
};
这里我们有类的接口和实现,其方法返回通过协变返回类型覆盖DummyBase
或DummyDerived
。再次使用虚拟继承。
// Setup
DerivedReturner returner;
returner.Ptr = &derived;
IBaseReturner* baseReturner = &returner;
现在从DummyDerived*
和DerivedReturner
返回DummyBase*
来自同一回归者IBaseReturner
:
DummyDerived* derivedOriginal = returner.Get();
DummyBase* baseFromInterface = baseReturner->Get();
比较obove:
std::cout << "Derived Original : " << derivedOriginal << std::endl;
std::cout << "Base from Interface : " << baseFromInterface << std::endl;
输出
Derived Original : 00000000002CF838
Base from Interface : 00000000002CF838
与上面不同,指针具有SAME值。 现在比较一下:
std::cout << "IsSame : " << (baseFromInterface == derivedOriginal) << std::endl;
输出:
IsSame : 0
比较返回false
即使地址相同也很难。这是预期的,因为指向DummyBase
的指针应具有不同的值。
在尝试dynamic_cast时也是如此:
std::cout << dynamic_cast<DummyDerived*>(baseFromInterface);
抛出了expception:
unknown file: error: C++ exception with description "Access violation - no RTTI data!" thrown in the test body.
显然,因为指针没有正确偏移。
似乎在调用IBaseReturner::Get
时,visual-c ++编译器无法执行必要的指针算法来将DummyDerived*
强制转换为DummyBase*
。这发生在vs2013和vs2015(没有尝试任何其他版本)。此外,当使用gcc编译时,它可以正常工作。
虽然设置可能有点复杂但问题却相当简单:
这是一个msvc错误还是我导致了未定义的行为?
添加了一个在线示例:http://rextester.com/KHZXGQ27304