首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >实现家族树时C++核心转储错误

实现家族树时C++核心转储错误
EN

Stack Overflow用户
提问于 2020-04-05 14:20:29
回答 3查看 79关注 0票数 2

我在努力实现族谱。我的类PersonTree定义如下:

FamilyTree.hpp**:** 文件

代码语言:javascript
运行
复制
using namespace std;
#include <string>

namespace family{

    class Person{
        public:
        string name;
        Person* mother;
        Person* father;

        Person(string name);

    };

    class Tree{
        public:
        Person* root;

        Tree(string name);

        Tree& addFather(string name1, string name2);
        Tree addMother(string name1, string name2);
        void display();
        string relation(string name);
        string find(string name);
        void remove(string name);
    };

};

FamilyTree.cpp**:** 文件

代码语言:javascript
运行
复制
#include "FamilyTree.hpp"
#include <string>
#include <iostream>
using namespace family;   

// FUNCTIONS

Person& findPerson(Person& root, string child_name){
    if (root.name.compare(child_name) != 0)
    {
        cout<<root.name<<":1"<<endl;
        findPerson(*root.father, child_name);
    }
    else if(root.name.compare(child_name) == 0){
        cout<<root.name<<":2"<<endl;
        return root;  
    }else{
        cout<<"not found!!!"<<endl;
        Person p("no found");
        return p;
    }
}

// PERSON
family::Person::Person(string person_name){
    name = person_name;
    father = nullptr;
    mother = nullptr;
};

// TREE
family::Tree::Tree(string name){
    root = new Person(name);
};

family::Tree& Tree::addFather(string child, string father){
    Person& child_found = findPerson(*root, child);

    //cout<<"child_found.name:"<<child_found.name<<endl;
    child_found.father = new Person(father);
    return *this;
    };

family::Tree family::Tree::addMother(string name1, string name2){return Tree("");};
void family::Tree::display(){};
string family::Tree::relation(string name){return "";};
string family::Tree::find(string name){return "";};
void family::Tree::remove(string name){};

int main(){
    Tree t("X");

    t.addFather("X", "Y");
    t.addFather("Y","Z");
    return 0;
}

我从addFather()函数开始:addFather("child", "new father"),用于为现有的子项目添加新父亲。我使用findPerson()函数递归地实现了它,该函数返回子函数的Person对象,addFather() func创建新的Person并将其初始化为创建子函数。

在我添加了两个父亲后,我得到了非法指令(核心抛出)错误,应该是什么问题?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-04-05 14:50:09

如果打开警告,就会发现您并不总是从findPerson返回。在这个职能中

代码语言:javascript
运行
复制
Person& findPerson(Person& root, string child_name){
    if (root.name.compare(child_name) != 0)
    {
        cout<<root.name<<":1"<<endl;
        findPerson(*root.father, child_name);      // (1)
    }
    else if(root.name.compare(child_name) == 0){
        cout<<root.name<<":2"<<endl;
        return root;  
    }else{
        cout<<"not found!!!"<<endl;
        Person p("no found");
        return p;                      // (2)
    }
}

第一个if-branch中标记为(1)的代码需要返回递归查找的人员,如下所示

代码语言:javascript
运行
复制
return findPerson(*root.father, child_name);

这应该能解决分段故障。

但是,在这个函数的最后一个分支中还有一个更深层次的问题,您将返回一个局部变量p的引用,标记为(2)。如果这样做,您将返回一个悬空引用,因为当函数返回时,p将超出作用域。

如果找不到人,您需要考虑这个函数应该做什么。

std::optional<Person>.

  • 您可以返回一个Person*,所以nullptr意味着找不到任何人。
  • 您可以返回一个Person*
票数 2
EN

Stack Overflow用户

发布于 2020-04-05 14:50:48

问题是不能返回对本地对象的引用。THis将导致未定义的行为。

当您添加一个新成员时,findPerson()将不会尝试返回这样一个本地对象p。这注定会失败。

这个设计不是最优的。可能的解决办法:

  • 声明一个静态对象p,该对象在什么都找不到时返回。与本地不同,静态保持活动,然后返回的引用将保持有效。但是,您必须确保返回的引用不会以更改静态对象名称的方式使用。
  • 更改findPerson()的接口,使其返回指针。它要么返回指向某个人的有效指针,要么返回nullptr (如果没有找到)。这是一个常见的成语(在实际开发中,您将返回一个迭代器,但是如果您是从C++开始的,这暂时太复杂了)。如果没有发现任何异常,
  • 将抛出异常,并重写调用代码,以便捕获异常。我不建议在这里使用这种方法:对于非常特殊的情况,最好保留例外。

注意,如果有其他错误,我没有查看您的代码。我只是在第一次尝试找到当树是空的时候不存在的东西时就停了下来。

票数 1
EN

Stack Overflow用户

发布于 2020-04-07 16:20:15

它适用于父亲的搜索,但我需要它来遍历所有的树。当我加上母亲根的时候,核心又被倾倒了。

代码语言:javascript
运行
复制
Person& findPerson(Person& root, string child_name){
    if (root.name.compare(child_name) != 0)
    {
        //cout<<root.name<<":1"<<endl;
        return findPerson(*root.father, child_name); 
        return findPerson(*root.mother, child_name);     // (1)
    }
    else if(root.name.compare(child_name) == 0){
        //cout<<root.name<<":2"<<endl;
        return root;  
    }else{
        throw exception();                     
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61044069

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档