【问题标题】:Using unique_ptr as a member class and with list使用 unique_ptr 作为成员类和列表
【发布时间】:2021-06-08 09:46:32
【问题描述】:

我最近做了一个包含 1 个超类和 2 个子类的应用程序。它的主要思想是将信息存储在3个不同的列表中。我的问题是,你可以只为所有 3 个类使用 1 个列表吗?即使 2 个子类有一些额外的成员。有人告诉我,您可以使用 unique_ptr 作为超类的成员并只列出 1 个列表。我在互联网上读过它,但我不太明白。有什么建议?感谢您的宝贵时间。

class Student {

     std::string Name;
     std::string Pinfo;
    std::map < std::string, float > Ngradelist;

public:

    std::string getName() {return Name;}

    std::string getPinfo() {return Pinfo;}

    virtual void InsertGradeList(std::string a, float b) {

        for(auto& it : Ngradelist)
            Ngradelist.insert(std::pair <std::string, float > (a,b));
    }

    Student( std::string n,  std::string p, std::map < std::string, float > Ng) :
        Name(std::move(n)), Pinfo(std::move(p)), Ngradelist(std::move(Ng)) {}

    virtual void Display() {

        std::cout << "Name: " << Name << std::endl;
        std::cout << "Personal information: " << Pinfo << std::endl;
        std::cout << "NCourse:" << std::endl;
        for(auto& it : Ngradelist)
            std::cout << "   " << it.first << "   Grade: " << it.second <<  std::endl;
    }
};

class HWStudent : public Student {

    std::string FieldOfWork;
    std::map<std::string, float> HWgradelist;

public:

    void InsertGradeList(std::string a, float b) override{

        for (auto &it : HWgradelist)
            HWgradelist.insert(std::pair<std::string, float>(a, b));
    }

    HWStudent(std::string n, std::string p, std::map<std::string, float> Ng, std::string f,
            std::map<std::string, float> HWg) : Student(std::move(n), std::move(p), std::move(Ng)),
            FieldOfWork(std::move(f)), HWgradelist(std::move(HWg)) {}

    void Display() override {

        Student::Display();
        std::cout << "Field of Work: " << FieldOfWork << std::endl;
        std::cout << "HWCourse:" << std::endl;
        for(const auto& it : HWgradelist)
            std::cout << "   " << it.first << "   Grade: " << it.second <<  std::endl;
    }
};

class SWStudent : public Student {

    std::map<std::string, float> SWgradelist;
    std::list < std::string > Languages;

public:

    void InsertGradeList(std::string a, float b) override {

        for (const auto &it : SWgradelist)
            SWgradelist.insert(std::pair<std::string, float>(a, b));
    }

    SWStudent(std::string n, std::string p, std::map<std::string, float> Ng, std::list < std::string > l,
              std::map<std::string, float> SWg) : Student(std::move(n), std::move(p), std::move(Ng)),
              Languages(std::move(l)), SWgradelist(std::move(SWg)) {}

    void Display() override {

        Student::Display();
        std::cout << "SWCourse:" << std::endl;
        for(const auto& it : SWgradelist)
            std::cout << "   " << it.first << "   Grade: " << it.second <<  std::endl;
        std::cout << "SW Languages:" << std::endl;
        for(const auto& it : Languages)
            std::cout << "   " << it << std::endl;
    }
};

std::list < Student > listaStudenti;
std::list < HWStudent > HWlistaStudenti;
std::list < SWStudent > SWlistaStudenti;

    void InsertListaStudenti(unsigned short option) {
        unsigned short numbers;
        std::string name , pinfo, course, fieldofwork, hwcourse, swcourse;
        std::string language;
        float grade = 0, hwgrade, swgrade;
        std::list < std::string > languagelist;
        if(option == 1) {
            std::cout << "Insert name: ";
            std::cin >> name;
            std::cout << "Insert personal information: ";
            std::cin >> pinfo;
            std::cout << "Insert course: ";
            std::cin >> course;
            std::cout << "Insert grade: ";
            std::cin >> grade;
            Student student(name, pinfo, {{course, grade}});
            listaStudenti.push_back(student);
        }
        if(option == 2) {
            std::cout << "Insert name: ";
            std::cin >> name;
            std::cout << "Insert personal information: ";
            std::cin >> pinfo;
            std::cout << "Insert course: ";
            std::cin >> course;
            std::cout << "Insert grade: ";
            std::cin >> grade;
            std::cout << "Insert hwcourse: ";
            std::cin >> hwcourse;
            std::cout << "Insert hwgrade: ";
            std::cin >> hwgrade;
            std::cout << "Insert fieldofwork: ";
            std::cin >> fieldofwork;
            HWStudent hwstudent(name, pinfo, {{course, grade}}, fieldofwork,{{hwcourse, hwgrade}});
            HWlistaStudenti.push_back(hwstudent);
        }
        if(option == 3) {
            std::cout << "Insert name: ";
            std::cin >> name;
            std::cout << "Insert personal information: ";
            std::cin >> pinfo;
            std::cout << "Insert course: ";
            std::cin >> course;
            std::cout << "Insert grade: ";
            std::cin >> grade;
            std::cout << "Insert swcourse: ";
            std::cin >> swcourse;
            std::cout << "Insert swgrade: ";
            std::cin >> swgrade;
            std::cout << "How many  languages: ";
            std::cin >> numbers;
            for(auto it = 0;it < numbers; ++it) {
                std::cout << "Insert language: ";
                std::cin >> language;
            languagelist.push_back(language);
            }
            SWStudent swstudent(name, pinfo, {{course, grade}},languagelist,{{swcourse, swgrade}});
            SWlistaStudenti.push_back(swstudent);
        }
    }

int main() {

    unsigned short option = 10;
    while(option != 0) {
        std::cout << "1.Add student." << std::endl;
        std::cout << "2.Add HW student." << std::endl;
        std::cout << "3.Add SW student." << std::endl;
        std::cout << "4.Display Student." << std::endl;
        std::cout << "5.Display HW Student." << std::endl;
        std::cout << "6.Display SW Student." << std::endl;
        std::cout << "0 is for exit." << std::endl;
        std::cout << "Option is : ";
        std::cin >> option;
        switch  (option) {
            case 0 : {
                std::cout <<" You chose to leave.";
                exit;
                break;
            }
            case 1 : {
               InsertListaStudenti(option);
                break;
            }
            case 2 : {
                InsertListaStudenti(option);
                break;
            }
            case 3: {
                InsertListaStudenti(option);
                break;
            }

            case 4: {

                for(auto &it : listaStudenti)
                    it.Display();
                break;
            }
            case 5: {
                for(auto &it : HWlistaStudenti)
                    it.Display();
                break;
            }
            case 6: {
                for(auto &it : SWlistaStudenti)
                    it.Display();
                break;
            }
        }

    }
}

【问题讨论】:

    标签: c++ list oop c++11 unique-ptr


    【解决方案1】:

    你确实可以拥有

    std::list<std::unique_ptr<Student>> students;
    

    而不是

    std::list<Student> listaStudenti;
    std::list<HWStudent> HWlistaStudenti;
    std::list<SWStudent> SWlistaStudenti;
    
    • 插入类似于

      Student student(name, pinfo, {{course, grade}});
      students.push_back(std::make_unique<Student>(std::move(student)));
      // or std::make_unique<Student>(name, pinfo, std::map<std::string, float>{{course, grade}})
      
      HWStudent hwstudent(name, pinfo, {{course, grade}}, fieldofwork, {{hwcourse, hwgrade}});
      students.push_back(std::make_unique<HWStudent>(std::move(hwstudent));
      

      而不是

      Student student(name, pinfo, {{course, grade}});
      listaStudenti.push_back(student);
      
      HWStudent hwstudent(name, pinfo, {{course, grade}}, fieldofwork,{{hwcourse, hwgrade}});
      HWlistaStudenti.push_back(hwstudent);
      
    • 问题在于您的“过滤”:

      for (auto& student : SWlistaStudenti) {
          student.Display();
      }
      

      变成

      for (auto& studentPtr : SWlistaStudenti) {
          if (auto ptr = dynamic_cast<SWStudent*>(studentPtr.get())) ptr->Display();
      }
      

      但是(只显示普通学生(不是硬件/软件))

      for(auto& student : listaStudenti) { student.Display(); }
      

      变成

      for (auto& studentPtr : students) {
          if (!dynamic_cast<SWStudent*>(studentPtr.get())
              && !dynamic_cast<HWStudent*>(studentPtr.get())) {
              studentPtr->Display();
          }
      }
      
    • 一个列表允许将它们平等对待 BTW:

      显示所有学生:

      for (auto& studentPtr : students) { studentPtr->Display(); }
      

      而不是

      for (auto& student : listaStudenti) { student.Display(); }
      for (auto& student : HWlistaStudenti) { student.Display(); }
      for (auto& student : SWlistaStudenti) { student.Display(); }
      

    【讨论】:

    • std::make_unique 是 C++14,但可以在 C++11 中实现。
    • 根据您的需求,虽然 IMO 3 个容器似乎更好。
    • 谢谢先生。我已经进行了更改,并且可以正常工作。我怎样才能只显示 HW 学生或只显示 SW 学生?我已经更改了您的 if 语句(其中包含动态转换的语句),以便它适用于 HW 或 SW 学生,但是当我尝试显示它时,控制台上没有任何弹出。显示所有学生或仅显示普通学生的作业。 (我只是想更多地了解 c++ 及其工作原理,通过这个例子,我从简单的构造函数开始,到现在的样子,当我进一步开发这个应用程序时,我学到了更多的 c++,我发现例子更容易,不仅仅是阅读理论)
    • 对不起,我是盲人。我看到它是旧列表(仅用于 SWStudents),并没有注意它。再次感谢您,祝您有美好的一天。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-26
    • 2017-07-24
    • 2020-07-17
    • 2019-12-28
    • 1970-01-01
    • 2017-01-15
    相关资源
    最近更新 更多