0

Ok, so, I know how to use java classes, but there is something about c++ classes that I don't get. My professor wants us to be able to add the name of a classes a student is taking and its grade to a stl list of Records that is in a Class of Student and then in other functions traverse and print out the information. I know how to use structs and functions and even classes from other languages, but how do I declare and then use them in c++? I have currently created what I have below from the basic model he gave us, but for example, I added the list & head to the printRecords() function deceleration in the class student, but I don't know if I do that. and how do I truly pass the list into a function, or in my function addClass(), actually add the information to the list? I didn't add the list & head to the function definition of addClass() and I am just trying to use it by its list name of st_records and it isn't giving me any errors when I build it, but, that seems odd to me since it is listed under private in the class deceleration... is it because it is still within the header file?

//////// This is my header file copied
#ifndef _BIKES_H_ 
#define _BIKES_H_
#include <fstream>
#include <string>
#include <iostream>
#include <list>

using namespace std;

struct Record 
{ 
    string class_name;
    char grade; 
};

class Student 
{ 
    public:
        Student(string & name); 
        void printRecords(list<Record> & head);
        char gradeForClass(string & cl_name, list<Record>& head);
        string standing(int); 
        void addClass(string &, char); 
    private: 
        int numClassesTaken; 
        string st_name; 
        std::list<Record> st_records; 
};

/*********************** * Student::printRecords() 
* When called from the main(), this function prints the entire Student's record: 
* classes taken along with their grades. 
*/ 
void Student::printRecords(list<Record>& head) 
{ 
    for (auto it = head.begin(); it != head.end(); it++)
    {
        cout << "Class: " << it->class_name << " Grade: " << it->grade;
    }
}
/*********************** 
* Student::standing() 
* When called from the main(), this function should output: 
* "Freshman", "Sophomore", "Junior", "Senior", 
* depending on the number of classes successfully(!) taken. 
* The exact implementation (in the part of 
* how many classes needed to advance to the next level) is up to you. 
* But this function should not iterate over the list of Records, or call std::list's 
* size() to determine the number of classes. You have a variable for that in
* the Student's class. 
* Note that this function returns string by value. 
*/ 
string Student::standing(int num) 
{ 
    int classes = num / 4;
    string ret = "";

    switch (classes)
    {
    case 0: ret = "Freshman"; break;
    case 1: ret = "Sophmore"; break;
    case 2: ret = "Junior"; break;
    case 3: ret = "Senior"; break;
    default: ret = "Not a normal path"; break;
    }
    return ret;
}

/*********************** 
* Student::gradeForClass() 
* Parameter: A class name. 
* Return type: a single character of grade. 
* Behavior: 
* When called from the main(), this function shall find a class by its name 
* in the Student's Records and output the grade for that class. 
* In case there is no such class in the Records, you shall output the value, 
* somehow reflecting that. 
*/ 
char Student::gradeForClass(string & cl_name, list<Record>& head)
{ 
    for (auto it = head.begin(); it != head.end(); it++)
    {
        if (it->class_name.compare(cl_name) == 0)
        {
            return it->grade;
        }
    }
}

/*********************** 
* Student::addClass() 
* When called from the main(), this function creates a new Record and adds that to 
* the list of Student's Records. It also increments the numClassesTaken, 
* which will be used to determine a Student's standing. 
*/ 
void Student::addClass(string & cl_name, char  grade_)
{ 
    Record* r = new Record();
    r->class_name = cl_name;
    r->grade = grade_;

    st_records.push_back(*r);
}
#endif

  • Does [this](https://stackoverflow.com/q/860339/1593077) answer your question? Otherwise, please focus it a bit more. – einpoklum Apr 25 '20 at 09:22
  • Two more differences between C++ and Java are that C++ doesn't have a garbage collector, and that in C++ objects (instances of classes and structs) can exist "on the stack". So the body of your addClass method could be `Record r; r.class_name = cl_name; r.grade = grade_; st_records.push_back(r)` and that way you wouldn't leak memory. Because you've tagged this C++17, you could even try just `st_records.push_back( {cl_name, grade_} );` – Allison Lock Apr 25 '20 at 09:28

2 Answers2

2

In C++ when a class has a member function, that member function has access to all of the data members of that class of the instance the function was called on.

Thus, you do not need to pass the records list into the class function, it already has access to it and can reference it by its name st_records.

public, protected and private specify access that "others" have. So public means anyone can access that classes data. protected means it can access its members, and any derived classes can as well, private means only it can access that data. But all of "it" has access, all of its functions.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
DClyde
  • 96
  • 2
  • I'd even say that a member function has access to all the data members of that class of the instances it has access - included but not necessarily limited to the instance the function was called on. – Jaffa Apr 25 '20 at 09:24
  • Excellent addition, yes very true. – DClyde Apr 25 '20 at 09:27
  • 1
    All this is true but it's also true in Java, which the OP says they understand. So I wonder if this gets to the heart of the OP's confusion. – john Apr 25 '20 at 09:36
1

Your addClass function is written as if it was Java

void Student::addClass(string & cl_name, char  grade_)
{ 
    Record* r = new Record();
    r->class_name = cl_name;
    r->grade = grade_;
    st_records.push_back(*r);
}

This is correct in Java, but leaks memory in C++. Here's the correct C++.

void Student::addClass(const string & cl_name, char grade_)
{ 
    Record r;
    r.class_name = cl_name;
    r.grade = grade_;
    st_records.push_back(r);
}

In C++ not every object has to be allocated with new. In fact it's often considered bad style to explicitly use new in C++.

I have no idea why you think this code (or your version) might not be adding the record to the list. In this respect C++ and Java work exactly the same.

Your printRecords function is wrong, but again the correct code is just like the Java code would be, so I'm still not sure what it is you aren't getting. Here's the correct code

void Student::printRecords() const
{ 
    for (auto it = st_records.begin(); it != st_records.end(); it++)
    {
        cout << "Class: " << it->class_name << " Grade: " << it->grade;
    }
}

Obviously the list you want to print is the class list, not a list passed in as a parameter. The only novel aspect of this method is that in C++ it should be declared const, since it doesn't modify the object.

I can only think that the differences between C++ and Java have overwhelmed you and you're missing the places where they are the same. Although there are lots of technical differences, they are similar in the way they implement object orientation.

john
  • 85,011
  • 4
  • 57
  • 81
  • Interesting, why should you use const? I have head that before but never quite understood. the function doesn't really have any way for it to change the object if it wanted to anyways right? Also, the basic structure that my teacher wrote has a constructor so that I must take a name parameter, but he doest seem to have made anything take that parameter. I see the st_name at the bottom which maybe he forgot to do that? Or can I just use it the way it is and call "name" in the functions? – The wandering student Apr 25 '20 at 21:55
  • C++ won't let you call a non-const method on a const object, const reference or const pointer (for hopefully obvious reasons) so unless you decalre `printRecords` const you won't be able to print const objects, or any object through a const reference/pointer. Basically every method you write in C++ you should ask yourself is this a const method or not and declare it appropriately. – john Apr 26 '20 at 05:26
  • Again I'm confused because this is no different to Java. st_name is the name of the class variable, name is just a parameter to the constructor, so st_name is what you must use in other methods of the class. Maybe your professor made a mistake but you're seeing differences where none exist. – john Apr 26 '20 at 05:30