Encapsulating user input for a class

For assignment, I made a simple C ++ program that uses a superclass (Student) and two subclasses ( CourseStudent and ResearchStudent ) to save a list of students and print their data, with various details shown for two different types of students (using method overrides display() from Student ).

My question is how the program collects information from the user about such things as the student’s name, identification number, device and payment information (for the student of the course) and research information (for research students):

My implementation has a request for user input and collection of this input, processed inside the classes themselves. The rationale for this was that each class knows what input data it needs, so it makes sense for me to know how to ask it (given what to ask through, and istream to collect input).

My lecturer says that the prompt and input should be processed in the main program, which seems to me more erratic, and it would be more difficult to expand the program to handle various types of students.

I take it as a compromise to create a helper class that processes the request and collects user input for each type Student , which can then be called by the main program. The advantage of this would be that there are not many of them in student classes (therefore they are cleaner), but they can also be associated with auxiliary classes if input functions are required. This also means that additional Student classes can be added without the need for major changes to the main program if auxiliary classes are provided for these new classes. Also, the auxiliary class can be replaced for an alternative language version without making any changes to the class itself.

What are the main advantages and disadvantages of three different user input options (fully encapsulated, helper class, or main program)?

+4
source share
3 answers

As mentioned in scv , it is usually better to separate the view (view) from the internal structure (model).

Here you have a typical case:

  • class Student , the root of the model hierarchy
  • the Displayer class, the root of another independent hierarchy

The problem with the display is that it varies depending on two elements, which requires a dual-send system (using virtual).

This is traditionally solved using the Visitor Template .

First check the base classes:

 // student.h class Displayer; class Student { public: virtual ~Student(); virtual void display(Displayer& d) const = 0; // display should not modify the model }; // displayer.h class Student; class CourseStudent; class ResearchStudent; class Displayer { public: virtual ~Displayer(); virtual void display(const Student& s) = 0; // default method for students // not strictly necessary virtual void display(const CourseStudent& s) = 0; virtual void display(const ResearchStudent& s) = 0; }; 

And now, let a few be implemented:

 // courseStudent.h #include "student.h" class CourseStudent: public Student { public: virtual void display(Displayer& d) const; }; // courseStudent.cpp #include "courseStudent.h" #include "displayer.h" // *this has static type CourseStudent // so Displayer::display(const CourseStudent&) is invoked void CourseStudent::display(Displayer& d) const { d.display(*this); } // consoleDisplayer.h #include "displayer.h" class ConsoleDisplayer: public Displayer { public: virtual void display(const Student& s) = 0; // default method for students // not strictly necessary virtual void display(const CourseStudent& s) = 0; virtual void display(const ResearchStudent& s) = 0; }; // consoleDisplayer.cpp #include "consoleDisplayer.h" #include "student.h" #include "courseStudent.h" #include "researchStudent.h" void ConsoleDisplayer::display(const Student& s) { } void ConsoleDisplayer::display(const CourseStudent& s) { } void ConsoleDisplayer::display(const ResearchStudent& s) { } 

As you can see, the tricky part is that if I want to add a new derived Student class, then I need to add a new virtual method to the Displayer and override it in each Displayer derived class ... but otherwise it works fine.

The advantage is that the display logic is now separate from the model, so we can add a new display logic without affecting our model.

+1
source

I think your teacher wanted to say, "Don't put him in student classes."

As Vlad said, the models will be student classes. Performance should not be in student classes. The idea is that student classes should store structural information about this object. How this data is presented depends on what the class uses. If, for example, you used these classes later for both the console application and the GUI application, you would not want to have display code in these classes. It really depends on the application using the classes.

The view / controller will be in the helper class or main program. Being in the main program does not mean that it should be dirty. You can have many functions to make main () look nice and clean, but the same would be true if you write it in a helper class. You will have all of these features, and possibly a few more.

I would suggest that if this is a small exercise, do not add an auxiliary class if you do not already have a clear idea of ​​what this class should be, or if you have time to spend figuring out.

+1
source

While I am skeptical of my advisers, I think that your adviser has the right argument here.

This may be too simplistic to understand how to nest cin / scanf in classes. But imagine that your student class forms the background code of some code with a graphical interface, and the data comes from a variety of things - radio buttons for the floor, combined fields for the age group, etc. You really should not put all this into your class of students.

The presence of a “viewer” or auxiliary class that fills the student’s help. I suggest having a class each depending on the type of view. You can do this inside the main one, but separate view classes will help you reuse the code.

Arpan

+1
source

Source: https://habr.com/ru/post/1305707/


All Articles