C++ 向下转换结构

C++ Downcasting a struct

我有以下代码:

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] 

我实际上尝试向它添加一个虚函数,但这并没有解决我的实际问题(我不知道如何在这里正确地向下转换)

这是未定义的行为。

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

从 cppreference.com 到 dynamic_cast

dynamic_cast < new_type > ( expression )      

If the cast is successful, dynamic_cast returns a value of type new_type. If the cast fails and new_type is a pointer type, it returns a null pointer of that type.

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

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

无论如何,因为您处理的是对象实例而不是指针,所以这永远行不通。您的列表包含 Operation 对象, 而不是 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 语句。

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

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

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

此外,你必须给Operation结构添加一个虚拟析构函数,否则你会发生内存泄漏,因为派生的列表class (FilterOperation) 在您删除 Operation.

时不会被释放