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

时间:2013-01-19 23:00:03

标签: c++ c++11 move

首先,我想说我对CPP很新(我从cpp11开始):) 考虑以下实体:学生(名字+姓氏)和组(描述+更多学生)。 我在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; }
};

主要是我有这个:

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方法有关。 在前2个案例中,参数是move(s),第三个案例是Student(...)。 我的猜测是学生(“fn3”,“ln3”)与学生s3(“fn3,”ln3“)相同,但如果我将s3传递给该函数,它将无法编译,并出现以下错误:无法从学生转换为学生&amp;&amp;

PS:如果你帮助我理解如何制作我认为理想的例子,我将不胜感激。 非常感谢你。

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

3 个答案:

答案 0 :(得分:1)

如果这确实是你的设计,你可以简化它并消除所有的智能指针和自定义结构:

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; }
};

答案 1 :(得分:0)

我建议您更改设计并使用智能指针。

为所有学生准备一个容器。

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

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

使用此设计,您还可以创建索引,以便根据不同的标准为学生订购。例如,您可以使用按名字排序的学生索引和按姓氏排序的学生的另一个索引。

答案 2 :(得分:0)

学生(“fn3”,“ln3”)是一个没有名字的临时对象。编译器决定它可以放弃,因为你没有机会再次使用它。在学生s2(“fn2”,“ln2”)的情况下 你在变量s2中保留对象的引用。因此,您必须使用move语句明确地将其弃去。