C++ C++;向下投射结构
我有以下代码:C++ C++;向下投射结构,c++,struct,downcast,C++,Struct,Downcast,我有以下代码: struct Operation { public : OperationName name; }; struct FilterOperation : Operation { FilterName filter; std::list<std::string> params; }; struct操作{ 公众: 操作名称; }; 结构过滤器操作:操作{ 过滤器名称过滤器; std::列表参数; }; OperationName
struct Operation {
public :
OperationName name;
};
struct FilterOperation : Operation {
FilterName filter;
std::list<std::string> params;
};
struct操作{
公众:
操作名称;
};
结构过滤器操作:操作{
过滤器名称过滤器;
std::列表参数;
};
OperationName和FilterName是列出每个操作和筛选器的所有不同名称的枚举
在遍历所有操作的for each循环中,我想将一个操作向下转换为FilterOperation:
std::list<Operation> operations
for (Operation op : operations) {
switch (op.name) {
case o_filter :
std::cout << dynamic_cast<FilterOperation*>(&op)->filter << std::endl;
}
}
std::列表操作
用于(操作op:操作){
开关(op.name){
案例o_过滤器:
std::cout filter这是未定义的行为
op
是一个操作
。不是指向操作
的指针或引用,小于过滤操作
。因此&op
显然不是过滤操作*
从cppreference.com下载:
dynamic\u cast(表达式)
如果强制转换成功,则dynamic_cast返回类型为new_type的值。如果强制转换失败且new_type为指针类型,则返回该类型的空指针
很明显,dynamic\u cast(&op)
是一个空指针,取消引用它是UB。关于添加虚拟函数的直觉应该为您解决了编译器错误。您确定没有遇到其他错误吗
在任何情况下,因为您处理的是对象的实例而不是指针,所以这永远不会起作用。您的列表由操作对象组成,而不是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;
}
}
std::列表操作
用于(操作*op:操作){
开关(操作->名称){
案例o_过滤器:
std::cout filter使用stl容器您可以使用操作的复制构造函数和操作符=
。
这些方法仅从过滤器操作
复制操作
,而不是复制整个结构
要解决此问题,您应该使用std::list
或者更好的方法,std::list
而不是std::list
这样,您就不会将操作复制到列表中,只需将指针
此外,必须将虚拟析构函数添加到操作
结构中,否则会出现内存泄漏,因为派生类中的列表(过滤器操作
)当你删除一个操作时不会被释放,但是-你有一个操作列表;它们不是filteroperations。即使它们基于filter操作,你也会对它们进行切片并丢失任何基于它们的filter对象。你能在操作对象列表中首先存储FilterOperation对象吗?我想st接受基类型,但也可以接受子结构,我可以更改列表以实现此行为吗?@jszpilewski:嗯,编译器没有抱怨这个:filterooperation op;operations.push_back(op);Im打开枚举值,而不是字符串您应该添加一个测试,测试动态_强制转换是否返回nullptr
,因为取消引用它是正确的UB@SergeBallesta是的,但我不想用与Estefull试图理解的内容没有直接关系的东西混淆答案。我认为他们的混淆源于不理解对象sli在C++中,它们可能来自java/.NET背景。知道检查Null pTR不是问题。好的,但是你至少应该在你的帖子中附加一条线。我同意这不是问题,但是你的代码不能因为UB直接使用。
dynamic_cast < new_type > ( expression )
std::list<Operation*> operations
for (Operation* op : operations) {
switch (op->name) {
case o_filter :
std::cout << dynamic_cast<FilterOperation*>(op)->filter << std::endl;
}
}