我有以下代码:
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]
我实际上尝试添加虚拟功能,但这并没有解决我的实际问题(我无法弄清楚如何正确地向下传播)
答案 0 :(得分:3)
这是未定义的行为。
op
是Operation
。不是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
时,将无法释放。