Building on ne555's comments:
class grade:
- You have dynamically allocated array of grades, and an individual member called grade. How are these related? When do you use arr and when do you use grade?
class student:
- Method names() is poorly named. It gets one name, not many.
- Since names() calls getline(cin,name), name must be a string. There's no reason for student to be a template if it only supports one template type.
- why have the classes() method? why not set v inside the constructor?
- Since it can only ever have 4 items, you could use an array instead of a vector, although that can lead to slightly more error prone code.
- names like v and getvect() aren't very useful. What does the vector represent?
- In method input: cout << "Math, English, History, Science" << endl; is fragile - meaning that it works but it's easily broken. What you mean to print is the contents of v. If you changed, for example to alphabetize it, to {"English","History","Math",Science"} then this line in input would be wrong.
method getgrades() is poorly named. First of all, don't put the class name in a method of the class. It's completely redundant. You wouldn't call this grades<T>::getGradesMethodForGradesClass(). Calling it getgrades() is only a little better. Second, "get" usually returns a value, and this one does, but it has the curious side effect of also printing out all the grades in arr. This should be called something like void print(ostream &); member grade is unnecessary and just confuses things.
Finally, ideally class student should have an instance of grades inside it. That instance would represent the grades for the student. Once you do this, methods to input and print a student will call the methods to input/print their grades.
Putting it all together:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
#include<iostream>
#include<string>
#include <vector>
using namespace std;
// This handles 4 grades. They can be numbers, letters, strings, whatever
template <class T>
class grades
{
public:
void input();
void print(ostream &os);
private:
static constexpr unsigned size=4;
T arr[size] {};
};
template<class T>
class student
{
public:
student();
void input(); // get the student name and grades
string getname() { return name; };
void print(ostream &);
private:
string name;
vector<string> classNames;
grades<T> gr;
};
template <class T>
void student<T>::input()
{
cout << "Enter in your name: ";
getline(cin, name);
cout << "Enter in the grades for the following: " << endl;
cout << "----------------------------------------" << endl;
cout << classNames[0];
for (unsigned i=1; i<classNames.size(); ++i) {
cout << ", " << classNames[i];
}
cout << '\n';
cout << "----------------------------------------" << endl;
gr.input(); // now read the grades
}
template <class T>
student<T>::student()
{
classNames = { "Math","English","History","Science" };
}
template <class T>
void student<T>::print(ostream &os)
{
for (unsigned i = 0; i < classNames.size(); i++) {
os << classNames[i] << '\t';
}
os << '\n';
gr.print(os);
}
template <class T>
void grades<T>::input()
{
for (unsigned i = 0; i < size; i++)
{
T grade;
cin >> grade;
arr[i] = grade;
}
}
template <class T>
void grades<T>::print(ostream &os)
{
for (unsigned i = 0; i < size; i++)
{
os << arr[i] << '\t';
}
os << '\n';
}
int main()
{
char anwser;
student<int> myStudent;
do {
myStudent.input();
myStudent.print(cout);
cout << "wish to keep going?(Y/N): ";
cin >> anwser;
} while (anwser == 'Y' || anwser == 'y');
}
|
$ ./foo
Enter in your name: Dave
Enter in the grades for the following:
----------------------------------------
Math, English, History, Science
----------------------------------------
92 78 83 95
Math English History Science
92 78 83 95
wish to keep going?(Y/N): n
|
This still isn't ideal. There should be a class that binds a school class name and a grade:
1 2 3 4
|
class StudentClass {
string name;
int grade;
};
|
This would replace both the grade class and the className vector. Instead a student would have a vector of StudentClass's:
1 2 3 4
|
class Student {
...
vector<StudentClass> classes; // classes that the student is enrolled in
};
|