Basically I need one Subject class and one Student class. One student can register for many subjects and one subject can have many students?
How can I connect the classes? Thanks.
With a set<>
(or unordered_set<>
where available) of the other class. Just make sure that when adding or removing a student/subject pair that both set<>
s are modified.
You will need more than a Subject and Student class.
Here's how I would implement it.
(And yes, Virginia, database concepts can be implemented in C++ without using database software).
Data Organization
Read up on Database Normalization.
The Faculty is referenced by both the Subject and the Student. This suggests that there be a separate table for Faculty. The Faculty fields in the Subject and Student structures shall link to entries in the Faculty table.
+------------+--------------+
| ID_Faculty | Faculty Name |
+------------+--------------+
The Subject record
The Subject record consists of two single item fields (Code and Faculty) and a container (of Students). Most relational databases hate records with containers in them, so the container must be factored out. In this case, a table of [Student, Subject] would suffice. When building the container for the subject record, this table would be searched for all entries with the same Subject ID and added to the container. To clarify the code, let us create separate records:
+------------+--------------+------------+--------------+
| ID_Subject | Subject_Code | ID_Faculty | Subject Name | <-- Subject_Entry
+------------+--------------+------------+--------------+
and
+------------+------------+
| ID_Subject | ID_Student | <-- Subject_Student_Record
+------------+------------+
Student Record
The Subject_Entry record satisfies the link to the ID_Subject field in the Subject_Student_Record. Now there needs something to satisfy the ID_Student field. Let us create the Student_Entry record:
+------------+------------+--------------+
| ID_Student | ID_Faculty | Student_Name |
+------------+------------+--------------+
This record contains the primitive or fundamental attributes of a student. The subjects that the student is enrolled in can be determined from the Subject-Student table.
Implementation The Student and Subject records want to be searched primarily by their ID fields and secondarily by their name fields. Choosing an appropriate C++ container or programming data structure is a matter of choice. For this simple exercise, there is no performance degradation for searching using a non-key field.
I suggest using std::map
for the Student and Subject records since the ID fields should be unique.
There are no unique keys in the Subject-Student table, so we can't exploit the performance benefit of a std::map
. Again, this is a small project so organizing the data for further optimization will produce negligible performace gains but massive complexity. So let's go with a std::vector
for the Subject-Student table.
Subjects and Students
These objects only have concept during input and output. Their attributes are contained by the above data structures. My suggestion would be to not have Subject and Student classes, but just retrieve their attributes. Your Mileage May Vary.
The actual implementation or coding is left as an exercise for the reader.
I probably wouldn't relate them In the real world, I would use a database and database statements to populate the controls you need on demand, if I really had to use classes, the only time I would use sets to store the relationships is if I needed to buffer 'reversible' changes or perform some mega-business logic on the complete set.
In the relational database world where every entry must have a unique primary key, you have a "registration" table, where each entry has one student and one subject, thus you have multiple registrations and can index them by student and also by subject.
You can do the same in C++ if you want, although you would need a multi-index of them. You can however easily create that yourself. This enables you to perform both 5 and 6.
You would store the pointer of the student object and the pointer of the subject object in this "registration" class though, not their "id". That way you can get directly to the student / subject and not have to look that up on a table too.
Of course if the method to register a student requires entering their id you would need to be able to match id to pointer. Students and subjects could be stored in a std::set or std::map with the id as the lookup.
Assuming you can't use boost multi-index (even if you are allowed to use shared_ptr, and you should be), you simply create a couple of vectors of pointers to the registration and sort them by student-id and subject-id (which you should be able to extract from registration as a simple "get" method).
精彩评论