Home > Enterprise >  Construct two classes that has attributes and can use methods of each other
Construct two classes that has attributes and can use methods of each other

Time:12-24

I'd like to know is it possible that two classes has attributes and can use methods of each other. For example, there're a class STUDENT and a class COURSE, a STUDENT have a list of joined courses and a COURSE have list of participants(students). I tried this:

in STUDENT.h

#include <iostream>
#include <vector>
// #include "COURSE.h"

class COURSE;

class STUDENT {
    string name;
    std::vector<COURSE*> listCourses;
public:
    STUDENT(){};

    addCourse(COURSE* &course){
        listCourses.push_back(course);
        course.addStudent(this);
    }
    
    string getName(){
       return this->name;
    }
    
    void showCourses(){
       for(COURSE* course : listCourses)
          std::cout << course->getName() << std::endl;
    }
};

in COURSE.h

#include <iostream>
#include <vector>
// #include "STUDENT.h"

class STUDENT;

class COURSE {
    string name;
    std::vector<STUDENT*> listStudents;
public:
    COURSE(){}

    addStudent(STUDENT* &student){
        listStudents.push_back(student);
        student.addCourse(this);
    }
      
    string getName(){
       return this->name;
    }
    
    void showStudent(){
       for(STUDENT* student : listCourses)
          std::cout << student->getName() << std::endl;
    }

};

If I include two classes each other, it said errors. If I just include one, just one class worked, other class has problem.

Can anyone help me to fix it and I wonder that is it necessary to use some design patterns or data structures to solve this. Thank you

CodePudding user response:

Yes, what you are attempting is possible, but not in the way you are attempting it. You need to separate your method declarations and definitions.

Also, you have a flaw in your add... methods that will lead to endless recursion as soon as a Student is added to a Course or vice versa. You need to detect when the two are already linked together so that you can avoid the loop.

Try something more like this:

Student.h

#ifndef StudentH
#define StudentH

#include <vector>
#include <string>

class Course;

class Student {
    std::string name;
    std::vector<Course*> listCourses;
public:
    Student() = default;
    ~Student();

    std::string getName() const;

    void addCourse(Course* course);
    void removeCourse(Course* course);
    void showCourses() const;
};

#endif

Student.cpp

#include "Student.h"
#include "Course.h"

#include <iostream>
#include <algorithm>

Student::~Student() {
    for(Course* course : listCourses) {
        course->removeStudent(this);
    }
}

std::string Student::getName() const {
    return name;
}

void Student::addCourse(Course* course) {
    if (std::find(listCourses.begin(), listCourses.end(), course) == listCourses.end()) {
        listCourses.push_back(course);
        course->addStudent(this);
    }
}
    
void Student::removeCourse(Course* course) {
    auto iter = std::find(listCourses.begin(), listCourses.end(), course);
    if (iter != listCourses.end()) {
        listCourses.erase(iter);
        course->removeStudent(this);
    }
}
    
void Student::showCourses() const {
    for(Course* course : listCourses) {
        std::cout << course->getName() << std::endl;
    }
}

Course.h

#ifndef CourseH
#define CourseH

#include <vector>
#include <string>

class Student;

class Course {
    std::string name;
    std::vector<Student*> listStudents;
public:
    Course() = default;
    ~Course();

    std::string getName() const;

    void addStudent(Student* student);
    void removeStudent(Student* student);
    void showStudents() const;
};

#endif

Course.cpp

#include "Course.h"
#include "Student.h"

#include <iostream>
#include <algorithm>

Course::~Course() {
    for(Student* student : listStudents) {
        student->removeCourse(this);
    }
}

std::string Course::getName() const {
    return name;
}

void Course::addStudent(Student* student) {
    if (std::find(listStudents.begin(), listStudents.end(), student) == listStudents.end()) {
        listStudents.push_back(student);
        student->addCourse(this);
    }
}
      
void Course::removeStudent(Student* student) {
    auto iter = std::find(listStudents.begin(), listStudents.end(), student);
    if (iter != listStudents.end()) {
        listStudents.erase(iter);
        student->removeCourse(this);
    }
}
    
void Course::showStudents() const {
    for(Student* student : listStudents) {
        std::cout << student->getName() << std::endl;
    }
}
  • Related