C++ 向下转换结构

C++ Downcasting a struct

本文关键字:结构 转换 C++      更新时间:2023-10-16

我有以下代码:

struct Operation {
public :
OperationName name;
};
struct FilterOperation : Operation {
FilterName filter;
std::list<std::string> params;
};

操作名称和过滤器名称是枚举,列出了每个操作和过滤器的所有不同名称。

在遍历所有操作的每个循环中,我想将操作向下转换为过滤器操作:

std::list<Operation> operations
for (Operation op : operations) {
switch (op.name) {
case o_filter :
std::cout  << dynamic_cast<FilterOperation*>(&op)->filter << std::endl;
}
}

显然,dynamic_cast在这里不起作用:

parser.cpp:154:90: error: cannot dynamic_cast ‘& op’ (of type ‘struct Operation*’) to type ‘struct FilterOperation*’ (source type is not polymorphic)
"Op: Filter, Name: " << filterStrings[dynamic_cast<FilterOperation*>(&op)->filter] 

我实际上尝试向其添加一个虚拟函数,但这并不能解决我的实际问题(我不知道如何在这里正确投射(

这是未定义的行为。

op是一个Operation.不是指向Operation的指针或引用,较少指向FilterOperation。所以&op显然不是FilterOperation*.

从 cppreference.com dynamic_cast:

dynamic_cast < new_type > ( expression )      

如果强制转换成功,dynamic_cast返回 new_type 类型的值。如果强制转换失败并且new_type是指针类型,则返回该类型的 null 指针。

很明显,dynamic_cast<FilterOperation*>(&op)是一个空指针,取消引用它是 UB。

你对添加虚函数的直觉应该已经为你解决了编译器错误。您确定没有收到其他错误吗?

在任何情况下,因为您处理的是对象的实例而不是指针,所以这永远行不通。您的列表由操作对象组成,而不是筛选操作对象。如果要插入 FilterOperation 对象,则需要指针列表(或者最好是shared_ptr(,而不是按值存储:

std::list<Operation*> operations
for (Operation* op : operations) {
switch (op->name) {
case o_filter :
std::cout  << dynamic_cast<FilterOperation*>(op)->filter << std::endl;
}
}

此外,我怀疑您误解了 switch(( 对字符串的作用。它可能不会做你想要的,你需要一个 if 语句。

使用 stl 容器,您可以使用复制构造函数和Operationoperator =。 这些方法仅复制FilterOperation而不是整个结构中的Operation

要解决此问题,您应该使用std::list<Operation*>甚至更好的std::list<std::shared_ptr<Operation>>而不是std::list<Operation>

这样,您就不会将操作复制到列表中,而只会将指针复制到列表中...

此外,您必须向结构添加虚拟析构函数Operation否则将出现内存泄漏,因为删除Operation时不会释放派生类 (FilterOperation( 中的列表。