C ++向下转换结构

时间:2018-06-07 11:05:01

标签: c++ struct downcast

我有以下代码:

struct Operation {
    public :
        OperationName name;
};

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

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

在每个循环执行所有操作的过程中,我想将操作向下转换为FilterOperation:

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] 

我实际上尝试添加虚拟功能,但这并没有解决我的实际问题(我无法弄清楚如何正确地向下传播)

3 个答案:

答案 0 :(得分:3)

这是未定义的行为。

opOperation。不是Operation的指针或引用,而是FilterOperation的较小者。因此&op显然不是FilterOperation*

来自c dynamic_cast上的cppreference.com:

dynamic_cast < new_type > ( expression )      
     

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

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

答案 1 :(得分:1)

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

在任何情况下,因为您正在处理对象而不是指针的实例,所以这将永远不会起作用。您的列表包含操作对象,不是 FilterOperation对象。如果要插入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语句。

答案 2 :(得分:1)

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

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

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

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