C++ 块类型是递归函数调用的有效错误
我有一个表示决策树的模块。我有两个类:Choice(从外部类事件继承)和Option。选项表示决策树的节点,选项表示分支。一个选项必须至少有一个选项。选项可以选择,也可以不选择。如果一个选项没有选择权,它就是一个终端选项 例如,如果决策树如下所示:C++ 块类型是递归函数调用的有效错误,c++,recursion,shared-ptr,C++,Recursion,Shared Ptr,我有一个表示决策树的模块。我有两个类:Choice(从外部类事件继承)和Option。选项表示决策树的节点,选项表示分支。一个选项必须至少有一个选项。选项可以选择,也可以不选择。如果一个选项没有选择权,它就是一个终端选项 例如,如果决策树如下所示: A----B | ----C----D | -----E 然后: A将是一个有两个选项(B和C)的选择。 B将是一个没有选择的选项(即终端选项)。 C将是一个有选择的选项。C的选择将包含选项D和E 我编写
A----B
|
----C----D
|
-----E
然后:A将是一个有两个选项(B和C)的选择。
B将是一个没有选择的选项(即终端选项)。
C将是一个有选择的选项。C的选择将包含选项D和E 我编写的代码允许决策树尽可能深入,这就是为什么选项有选项,选项有选项的原因 我有一个函数find_terminal_options_in(EventPtr ch),它带有一个递归调用,用于查找所有终端选项并获取它们的名称。在本例中,find_terminal_options_In(ptr_to_A)应返回{“B”、“D”、“E”}。相反,它在处理选项C的选择时,在第二次调用结束时失败。由于出现以下错误,因此失败: 调试断言失败
表达式:\块\类型\有效(pHead->nBlockUse) 在共享的_ptr析构函数中调用 发生此错误是因为我的设计中存在缺陷还是因为我使用共享ptr的方式存在缺陷?关于如何消除这个运行时错误,有什么建议吗 请参阅我的(简化)代码,它再现了问题:
class Event {
public:
Event(std::string name):name_(name) {};
std::string name() {return name_;};
virtual bool is_terminal() = 0;
protected:
std::string name_;
};
class Option;
class Choice: public Event {
public:
Choice(): Event("") {};
Choice(std::string name, std::list<Option> options): Event(name) {options_ = options;};
std::list<Option> options() {return options_;};
std::string name() {return name_;};
bool is_terminal() {return false;};
private:
std::list<Option> options_;
};
class Option
{
public:
Option(std::string name, Choice choice):name_(name),choice_(choice) {};
Option(std::string name):name_(name) {};
Choice choice() {return choice_;};
std::string choice_name() {return choice_.name();};
std::string option_name() {return name_;};
private:
Choice choice_;
std::string name_;
};
typedef std::shared_ptr<Event> EventPtr;
typedef std::shared_ptr<Event> ChoicePtr;
std::list<std::string> find_terminal_options_in(EventPtr ch);
int main() {
std::list<Option> temp_opts1;
temp_opts1.push_back(Option("D"));
temp_opts1.push_back(Option("E"));
Choice option_Cs_choice("option_Cs_choice",temp_opts1);
std::list<Option> temp_opts2;
temp_opts2.push_back(Option("C",option_Cs_choice));
temp_opts2.push_back(Option("B"));
EventPtr ptr_to_A = EventPtr(new Choice("A",temp_opts2));
std::list<std::string> terminal_options = find_terminal_options_in(ptr_to_A);
}
std::list<std::string> find_terminal_options_in(EventPtr ch)
{
std::list<std::string> returned_list;
std::shared_ptr<Choice> choice = std::dynamic_pointer_cast<Choice>(ch);
std::list<Option> choice_options = choice->options();
for(std::list<Option>::iterator options_it = choice_options.begin();options_it != choice_options.end(); options_it++)
{
if(options_it->choice_name() != "") //it has a choice
{
Choice option_choice = options_it->choice();
find_terminal_options_in(EventPtr(&option_choice));
}
else //it doesn't have a choice, and is therefore a terminal option
returned_list.push_back(options_it->option_name());
}
return returned_list;
}
类事件{
公众:
事件(std::string name):名称{(name){};
std::string name(){返回名称};
虚拟布尔是_terminal()=0;
受保护的:
std::字符串名称;
};
类别选择权;
课程选择:公共活动{
公众:
Choice():事件(“”{};
选项(std::string name,std::list options):事件(name){options_u=options;};
std::list options(){返回选项};
std::string name(){返回名称};
bool是_terminal(){return false;};
私人:
std::列出选项;
};
类选项
{
公众:
Option(std::string name,Choice-Choice):name_u(name),Choice_u(Choice){};
选项(std::string name):名称{(name){};
Choice Choice(){返回Choice_;};
std::string choice_name(){return choice_u.name();};
std::string选项_name(){return name_;};
私人:
选择,;
std::字符串名称;
};
typedef std::shared_ptr EventPtr;
typedef std::共享_ptr ChoicePtr;
std::在(EventPtr ch)中列出查找终端选项;
int main(){
std::列出临时选项1;
临时选项1.向后推(选项(“D”);
临时选项1.向后推(选项(“E”);
选项选择(“选项选择”,临时选项1);
std::列出临时选项2;
临时选项2.向后推(选项(“C”,选项“C”);
临时选项2.向后推(选项(“B”);
EventPtr ptr_to_A=EventPtr(新选项(“A”,临时选项2));
std::list terminal_options=在(ptr_to_A)中查找_terminal_options_;
}
std::列出查找终端选项(EventPtr ch)
{
std::列表返回\u列表;
std::shared_ptr choice=std::dynamic_pointer_cast(ch);
std::list choice_options=choice->options();
对于(std::list::iterator options_it=choice_options.begin();options_it!=choice_options.end();options_it++)
{
if(options\u it->choice\u name()
{
Choice option\u Choice=options\u it->Choice();
在(EventPtr(&option_choice))中查找终端选项;
}
else//它没有选择余地,因此是一个终端选项
返回的列表。向后推(选项\u it->选项\u name());
}
返回列表;
}
您的代码有两个问题:
find_terminal_options_in(EventPtr(&option_choice));
find_terminal_options_in(EventPtr(new Choice(option_choice)));
正确修复-存储指向选项的共享指针,而不是选项中的选项。问题是:您错过了
virtual ~Event() {}
课堂活动。
一旦从函数调用堆栈返回,实例“ch”就会被删除
std::list<std::string> find_terminal_options_in(EventPtr ch) { ... }
使用“virtual~Event()”进行尝试,问题将消失。:-)
virtual ~Event() {}
std::list<std::string> find_terminal_options_in(EventPtr ch) { ... }
EventPtr ptr_to_A = EventPtr(new Choice("A",temp_opts2));