我正在尝试实现家谱。我有如下定义的Person
和Tree
类:
文件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
并将其初始化为找到的子级。
添加两个父亲后,我得到非法指令(核心转储)错误,这应该是什么问题?
如果打开警告,您会发现并非总是从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>
。
问题是您无法返回对本地对象的引用。这将导致不确定的行为。
添加新成员时,findPerson()
不会尝试返回此类本地对象p。这注定要失败。
此设计不是最佳的。可能的解决方案:
findPerson()
的接口,使其返回指针。它要么返回指向某人的有效指针,要么如果找不到任何内容,则返回nullptr
。这是一个常见的习惯用法(在现实世界的开发中,您将返回一个迭代器,但是如果您使用C ++开始,那么这暂时太复杂了)。 请注意,如果还有其他错误,我不会查看您的代码。我只是在第一次尝试时停止,发现树为空时不存在的东西。