繁体   English   中英

MSVC:协变返回类型和虚拟继承

[英]MSVC: Covariant Return Types And Virtual Inheritance

我不确定这是 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; }
 };

这里我们有接口和类的实现,这些类的方法返回DummyBaseDummyDerived通过协变返回类型覆盖。 再次使用虚拟继承。

// Setup
DerivedReturner returner;
returner.Ptr = &derived;
IBaseReturner* baseReturner = &returner;

现在将DummyDerived*DerivedReturnerDummyBase*从同一个返回器转换为IBaseReturner

DummyDerived* derivedOriginal = returner.Get();
DummyBase* baseFromInterface = baseReturner->Get();

比较就像上面一样:

std::cout << "Derived Original    : " << derivedOriginal << std::endl;
std::cout << "Base from Interface : " << baseFromInterface << std::endl;

输出

Derived Original    : 00000000002CF838
Base from Interface : 00000000002CF838

与上面不同,指针具有相同的值。 现在比较它们:

std::cout << "IsSame  : " << (baseFromInterface == derivedOriginal) << std::endl;

输出:

IsSame  : 0

即使地址相同,比较也会返回false 这是预期的,因为指向DummyBase的指针应该具有不同的值。 同样在尝试 dynamic_cast 时:

std::cout << dynamic_cast<DummyDerived*>(baseFromInterface);

并抛出异常:

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

您的代码没有未定义的行为(GCC 和 Clang 都可以正常编译和执行,演示: https : //gcc.godbolt.org/z/q91vbhjTh ),并且由于 MSVC 中的错误,其运行失败,该错误仍然存​​在存在于 Visual Studio 2019 和 2022 中。

报告的 MSVC 错误: https : //developercommunity.visualstudio.com/t/Invalid-code-generated-for-virtual-inher/1598214

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM