如何管理对象之间的一对多关系?(移动相关)

How to manage one to many relationship between objects? ( move related )

本文关键字:关系 一对多 移动 之间 何管理 管理 对象      更新时间:2023-10-16

首先我想说我是CPP的新手(我从cpp11开始):)考虑以下实体:Student(名字+姓氏)和Group(描述+更多学生)。我在c++中创建了以下两个类:

class Student
{
private:
    std::string firstName;
    std::string lastName;
    Student(const Student &student);
    Student& operator=(const Student &student);
public:
    Student():firstName(""), lastName("") { }
    Student(std::string firstName, std::string lastName):firstName(firstName), lastName(lastName) { }
    Student(const Student &&student):firstName(student.firstName), lastName(student.lastName) { }
    Student& operator=(const Student &&student) { this->firstName=student.firstName; this->lastName=student.lastName; return *this; }
    std::string GetFirstName() const { return this->firstName; }
    std::string GetLastName() const { return this->lastName; }
};

class Group
{
private:
    std::string description;
    std::vector<std::shared_ptr<Student>> students;
    Group(const Group &group);
    Group& operator=(const Group &group);
public:
    explicit Group():description(""), students(std::vector<std::shared_ptr<Student>>()) { }
    explicit Group(std::string description) :description(description), students(std::vector<std::shared_ptr<Student>>()) { }
    void NewStudent(Student &&student) { students.push_back(std::make_shared<Student>(std::move(student))); }
    std::vector<std::shared_ptr<Student>> GetStudents() const { return students; }
};

在main中,我有这个:

Student s1("fn1","ln1");
Student s2("fn2","ln2");
//Student s3("fn3","ln3");
Group cppGroup("C plus plus");
cppGroup.NewStudent(std::move(s1));
cppGroup.NewStudent(std::move(s2));
cppGroup.NewStudent(Student("fn3", "ln3"));
//cppGroup.NewStudent(s3);
std::vector<std::shared_ptr<Student>> cppStudents=cppGroup.GetStudents();

我的问题与NewStudent方法有关。在前两种情况下,参数是move(s),在第三种情况下是Student(…)。我的猜测是,学生("fn3","ln3")与学生s3("fn3","ln3")相同,但如果我将s3传递给函数,它就不会编译以下错误:无法从学生转换为学生&&

PS:如果你帮助我了解如何使我认为理想的例子,我会很感激。非常感谢。

LE:我想我明白发生了什么,Visual Studio显示以下错误:不能将左值转换为右值所以我的猜测是,如果我传递给NewStudent s3,它不知道如何将其转换为右值,但如果我传递它Student("fn3", "ln3"),它将调用move构造函数。

如果这确实是你的设计,你可以大大简化它,去掉所有的智能指针和自定义结构函数:

class Student
{
private:
    std::string firstName;
    std::string lastName;
public:
    Student(std::string firstName, std::string lastName):firstName(firstName), lastName(lastName) { }
    std::string GetFirstName() const { return this->firstName; }
    std::string GetLastName() const { return this->lastName; }
};

class Group
{
private:
    std::string description;
    std::vector<Student> students;
public:
    explicit Group(std::string description) :description(description) { }
    void NewStudent(Student student) { students.push_back(student); }
    std::vector<Student> GetStudents() const { return students; }
};

Student("fn3", "ln3")是一个没有名称的临时对象。编译器决定它可以放弃它,因为您没有机会再次使用它。在学生s2("fn2","ln2")的情况下您在变量s2中保留了对对象的引用。所以你必须用move语句显式地给出它

我建议改变你的设计,使用智能指针。

给所有学生一个容器。

学生的将有一个或多个智能指针指向"所有学生"容器中的学生。

这个设计允许你在不复制学生对象的情况下拥有不同的主题组。Group包含将包含智能指针的副本。

使用这种设计,您还可以创建索引,根据不同的标准对学生进行排序。例如,您可以有一个按名字排序的学生索引和另一个按姓氏排序的学生索引。