c++ - 将 void 动态转换为类型的安全方法?
问题描述
我的 C++ 有点生疏,我不记得标准中的所有内容。
我有一个void*
. 在一个特定的函数中,它要么是继承 Alpha 的类,要么是继承 Beta 的类。两个基类都有虚函数。但是我似乎无法分辨哪个是哪个
class Alpha {
public:
virtual void Speak() { printf("A"); }
};
class Beta {
public:
virtual void Speak() { printf("B"); }
};
int main(){
//BAD CODE WILL PRINT TWICE
void *p = new Alpha;
Alpha*a = dynamic_cast<Alpha*>((Alpha*)p);
Beta*b = dynamic_cast<Beta*>((Beta*)p);
if(a)
a->Speak();
if(b)
b->Speak();
return 0;
}
我如何确定哪个班级是哪个班级?此代码库中有 100 个类被转换为 void。他们中的大多数都继承了 5 个基类,但我并不急于找出答案。在使用动态转换之前,唯一的解决方案是从类似的东西继承class Dummy {public: virtual void NoOp(){}};
并转换为 Dummy 吗?这安全吗?我希望有更好的解决方案,但我想不出别的。
解决方案
对指针唯一能做的void*
就是将它转换回与最初转换的指针完全相同的类型void*
。做任何其他事情的行为是未定义的。
在你的情况下你可以做的是定义
class Base
{
public:
virtual ~Base() = default; // make me a polymorphic type and make
// polymorphic delete safe at the same time.
};
并使其成为Alpha
and的基类Beta
。然后传递一个Base*
指针而不是一个指针void*
,然后直接将您dynamic_cast
的 s 放在p
.
进一步注意,如果您声明virtual void Speak() = 0;
in Base
,那么您的代码 inmain
将变得简单
int main(){
Base* p = new Alpha;
p->Speak();
delete p; // ToDo - have a look at std::unique_ptr
}
根据经验,任何类型的演员表都是不可取的。
推荐阅读
- adobe - 如何在 AEM 上编辑 Teaser 的选项卡选项顺序?
- php - 如何在laravel中附加循环?
- snowflake-cloud-data-platform - 函数 EXTRACT 不支持 SnowFlake 中的 NUMBER(38,0) 参数类型
- javascript - 如何使用清除按钮“清除”我的计时器?
- laravel - Guzzle Post 多部分/表单数据 Laravel
- jenkins - 持续集成管道
- azure - 无法将 azure postgresql 私有数据库连接到 powerBI 数据源?
- html - 尝试在 Angular 中使用 ng-upload 上传文件时遇到“TypeError: Cannot read properties of undefined (reading 'memes')”
- c# - 将数据库生成的 ID 添加到 Entity Framework Core 中的种子数据
- javascript - Atom 是否有一个插件可以忽略在评论中的搜索?