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

问题描述 投票:1回答:1

我正在尝试实现家谱。我有如下定义的PersonTree类:

文件FamilyTree.hpp

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

#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()函数创建新的Person并将其初始化为找到的子级。

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

c++ compiler-errors core coredump
1个回答
0
投票

如果打开警告,您会发现并非总是从findPerson返回。在此功能

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分支中标记为(1)的代码需要返回以递归方式找到的Person,像这样

return findPerson(*root.father, child_name);

应该注意段错误。

但是,此函数的最后一个分支存在更深的问题,在该分支中,您将返回对标记为(2)的局部变量p的引用。

如果未找到人,则需要考虑该功能应该怎么做。

  • 您可能会返回Person*,因此nullptr表示找不到人。

  • 您可以返回std::optional<Person>


0
投票

问题是您无法返回对本地对象的引用。这将导致不确定的行为。

添加新成员时,findPerson()不会尝试返回此类本地对象p。这注定要失败。

此设计不是最佳的。可能的解决方案:

  • 声明一个静态对象p,当没有发现任何东西时返回该对象。与本地人不同,静态保持活动状态,返回的引用将保持有效。但是,您必须确保不要以可能更改静态对象名称的方式使用此返回的引用。
  • 更改findPerson()的接口,使其返回指针。它要么返回指向某人的有效指针,要么如果找不到任何内容,则返回nullptr。这是一个常见的习惯用法(在现实世界的开发中,您将返回一个迭代器,但是如果您使用C ++开始,那么这暂时太复杂了)。
  • 如果未找到任何内容,则引发异常,并重写您的调用代码,以使其捕获异常。我不建议在这里使用这种方法:对于特殊情况,最好保留例外。

请注意,如果还有其他错误,我不会查看您的代码。我只是在第一次尝试时停止,发现树为空时不存在的东西。

© www.soinside.com 2019 - 2024. All rights reserved.