gpt4 book ai didi

c++ - 从多态容器中提取已知接口(interface)时的奇怪行为

转载 作者:IT老高 更新时间:2023-10-28 23:13:06 28 4
gpt4 key购买 nike

谁能帮我理解这种行为?简而言之:

  • 我已将多态对象存储在一个通用容器中。
  • 其中一些实现了特定的接口(interface)。我可以分辨出哪些。
  • 但是我不能使用这个界面。

以下是我总结的:

#include <iostream>
#include <vector>


// A base class
struct Base {
// A polymorphic method
virtual void describe() const {
std::cout << "Base" << std::endl;
};
virtual ~Base(){
std::cout << " Base destroyed" << std::endl;
};
};

// A specific interface
struct Interface {
virtual ~Interface(){
std::cout << " Interface Destroyed" << std::endl;
};
virtual void specific() = 0;
};

// A derived class..
struct Derived : public Base, public Interface {
virtual void describe() const {
std::cout << "Derived" << std::endl;
};
virtual void specific() {
std::cout << "Derived uses Interface" << std::endl;
};
virtual ~Derived() {
std::cout << " Derived destroyed" << std::endl;
};
};

int main() {

// Test polymorphism:
Base* b( new Base() );
Derived* d( new Derived() );
b->describe(); // "Base"
d->describe(); // "Derived"
// Ok.

// Test interface:
d->specific(); // "Derived uses Interface"
Interface* i(d);
i->specific(); // "Derived uses Interface"
// Ok.

// Here is the situation: I have a container filled with polymorphic `Base`s
std::vector<Base*> v {b, d};
// I know that this one implements the `Interface`
Interface* j((Interface*) v[1]);
j->specific(); // " Derived destroyed"
// " Interface destroyed"
// " Base destroyed"
// Why?! What did that object do to deserve this?

return EXIT_SUCCESS; // almost -_-
}

谁能告诉我我在那里缺少什么?

有趣的事实:如果我交换 Base::~BaseBase::describe 的定义,那么对象就会改为描述自己被摧毁。为什么顺序在方法声明中很重要?

最佳答案

这是避免 C 风格强制转换的一个很好的理由。当你这样做时:

Interface* j((Interface*) v[1]);

这是一个reinterpret_cast。 C 风格的强制转换将尝试按顺序执行:const_caststatic_caststatic_cast 然后 const_castreinterpret_castreinterpret_cast 然后是 const_cast。在这种情况下,所有这些类型转换都是错误的! reinterpret_cast 尤其是未定义的行为,老实说,你为什么看到你看到的特定行为并不重要。未定义的行为是未定义的。

你想要做的是:

Interface* j = dynamic_cast<Interface*>(v[1]);

这是通过运行时动态层次结构的正确转换,并且会给你 正确 Interface* 对应于 v[1] (或 nullptr,如果 v[1] 没有此运行时类型)。一旦我们解决了这个问题,j->specific() 就会打印出 Derived uses Interface,正如你所期望的那样。


问题可能与 vtable 对齐有关。当您进行重新解释转换时,由于 Base 没有 specific,因此该特定函数的偏移量可能与 ~Base(),所以效果是你直接调用了析构函数——这就是你看到你看到的东西的原因。

关于c++ - 从多态容器中提取已知接口(interface)时的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32076851/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com