1

I have a class student and constructor for name and age but latter on student must be able to edit that info. I tried following but edit info dont work:

class Student{
public:
    string name;
    int age;
    int grades[3];
    int assignments[4];

Student(string name, int age){
    this->name = name;
    this->age = age;
}

void edit_info(){
    string newName;
    int newAge;

    cout<<"Set new name:";
    cin>>newName;
    cout<<"Set new age:";
    cin>>newAge;

    this->name=newName;
    this->age=newAge;
    
}
void show_info(){
    cout<<name<<"\n";
    cout<<age<<"\n";
}

Code when I chose which student to "play":

if(input == "studentOne"){
        cout<<"You are now student 1\n";
        cout<<"What is your name:";
        cin >> s1_name;
        cout<<"How old are you:";
        cin >> s1_age;
        Student student1(s1_name, s1_age);
        while(true){
            CMD(student1);
        }

and CMD function:

void CMD(Student student){
string command;
cout<<"Type your command(edit_info, submit_assignments, sitFortest, show_info):";
cin>>command;

if(command=="edit_info"){
    student.edit_info();
}
else if(command=="show_info"){
    student.show_info();
}

}

Dot
  • 23
  • 3
  • Rename your member to "name_" or "m_name". It is a nice way to distinguish between members and local variables. `this->` is hardly ever needed (only some corner cases with class templates). Also unlearn `using namespace std;` and just type `std::` where you need it explicitely. Another tip : use [std::vector](https://en.cppreference.com/w/cpp/container/vector) for grades and assignments (std::vector is not a mathematical vector but a container.) – Pepijn Kramer Feb 19 '23 at 08:41
  • 2
    In what way does `edit_info` not work? It looks good to me. Please don't say 'it doesn't work' because more often that not it is not obvious why it doesn't work. Say how you know it doesn't work, say what your evidence is. – john Feb 19 '23 at 09:05
  • @john My evidence is that question. Do you think that this question would be there if my code would work? I activate function and when I check if values changed they don't. – Dot Feb 19 '23 at 10:19
  • @PepijnKramer By which thing do you think that I use namespace std? But thatnks. – Dot Feb 19 '23 at 10:20
  • @PepijnKramer Can you just quickly explain to me how is vector different as an array besides that I dont type how large index it has? – Dot Feb 19 '23 at 10:24
  • A vector will allocate and deallocate memory for you (as it grows). You can use it in a lot of the algorithms from the standard library (e.g. [sorting](https://en.cppreference.com/w/cpp/algorithm/sort), [minimum value](https://en.cppreference.com/w/cpp/algorithm/min_element)). They are easier to pass around (more like objects). If you want fixed size arrays there is also [std::array](https://en.cppreference.com/w/cpp/container/array) in C++. I like to use both more then "C" style arrays because it is very straightforward to check their size. (don't need to use sizeof(arr)/sizeof(arr[0])) – Pepijn Kramer Feb 19 '23 at 10:38
  • Don't panic :) There is just a lot to learn. I've been using C++ for almost 30 years now... and I am still learning also because C++ keeps changing for the better with each update. (This regretably also means a lot of the examples/books and teachers are not always up-to-date) – Pepijn Kramer Feb 19 '23 at 10:40
  • @Dot But that is faulty thinking. It could just as easily be that the code that checks the variables is wrong, or the code that calls that function is wrong. I'm sorry but we see this all the time, newbie has a problem, thinks they know the code that is at fault and posts it. But in reality the code posted is fine, and the bug is somewhere else. As I said I see nothing wrong with the code you have posted. If you also post the code that calls that function, and the code that checks if the variables have changed, then we could make some progress. – john Feb 19 '23 at 10:57
  • @john Okay I edited post and added show_info function that I used to check if name and age changed. Can you see something wrong. Because I know that both functions are called but not workign right. – Dot Feb 19 '23 at 11:07
  • @Dot I still see nothing wrong. Could you post the code that calls the two functions? My **guess** would be that (although you don't realise it) you are calling the two functions on two different objects. So the first object does change, but then you print out the second unchanged object. – john Feb 19 '23 at 11:13
  • @john Okey I added when I create object and function – Dot Feb 19 '23 at 11:33
  • [What is a debugger and how can it help me diagnose problems?](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems) – Jesper Juhl Feb 19 '23 at 11:45
  • @Dot As I expected you have multiple 'Student' objects, I'll write up an answer. – john Feb 19 '23 at 11:48

2 Answers2

0

To initialize member variables, give members a distinct naming scheme. (There are a few conventions around, I am used to prefixing with m_). And have a look at this : https://en.cppreference.com/w/cpp/language/constructor member initialization lists.

#include <vector>
#include <string>
#include <iostream>

class Student
{
public:
    Student(std::string name, unsigned int age) :
        m_name{ name }, 
        m_age{ age }
    {
        // don't initialize members in body use member initialization list.
        //this->name = name;
        //this->age = age;
    }

    void edit_info() 
    {
        // you can directly input into members.
        std::cout << "Set new name:";
        std::cin >> m_name;
        std::cout << "Set new age:";
        std::cin >> m_age;
    }

private: // class members should be private!
    std::string m_name;
    unsigned int m_age; // you don't execpt age to be < 0 so unsigned
    std::vector<int> grades;
    std::vector<int> assignments;
};
Pepijn Kramer
  • 9,356
  • 2
  • 8
  • 19
  • 2
    In initializer list `name{name}` will work perfectly fine, there's no need to change either name: https://godbolt.org/z/xoeKehTYx. – Yksisarvinen Feb 19 '23 at 09:29
  • @Yksisarvinen Heh funny never realized this worked too ;) Anyway I still find it usefull to tag members just for readability (but that's possibly just habit) – Pepijn Kramer Feb 19 '23 at 09:29
  • May I ask why members should be private? – Dot Feb 19 '23 at 10:12
  • @Dot good question : It is all about encapsulation. By providing public members we allow other code to access data that (most of the time) should not be accessible. With private members you can allow the member functions to do checking on the input, and more things. It also hides the internal implementation of your class from its users allowing you to change them later (refactoring). https://en.wikipedia.org/wiki/Encapsulation_(computer_programming) – Pepijn Kramer Feb 19 '23 at 10:34
0

This code

Student student1(s1_name, s1_age);
while(true){
    CMD(student1);
}

void CMD(Student student){
    ...
}

creates a new Student object each time that CMD is called. The object student in the CMD function is not the same as the object student1 in the calling function. So changes to this object have no effect on the object in the calling function.

This is because by default C++ uses call by value, meaning that objects are copied when passed as parameters. If you want to avoid this happening then you must use references.

The change is very simple

void CMD(Student& student){ // & means use call by reference

The extra & turns student into a reference to the calling variable, instead of a separate object. Now changes to student will actually change the object in the calling function, instead of changing a copy of the object in the calling function.

This is a common misunderstanding among beginners. Some languages do use call by reference, but in C++ the default is call by value.

john
  • 85,011
  • 4
  • 57
  • 81
  • It gives me an error: more than one instance of overloaded function "CMD" matches the argument list: -function "CMD(Student student)" (declared at line 88) -function "CMD(Student &student)" (declared at line 160) -argument types are: (Student) – Dot Feb 19 '23 at 12:05
  • @Dot You have to change the function signature in both places. – john Feb 19 '23 at 12:22
  • Do you mean when I call it like CMD(&student1) because I cant do that or where do I put &? – Dot Feb 19 '23 at 12:41
  • @Dot No, you don't need to change the function call. I mean `CMD` is a function, what you have posted is the function *definition* but somewhere else in your code (probably near the start) you also have the function *prototype* (aka the function declaration). The definition and the prototype must match, so if you add a `&` to the definition you also add a `&` to the prototype. Make sense? – john Feb 19 '23 at 12:48
  • @Dot In fact the error message is telling you where, the prototype is at line 88, the definition is at line 160. – john Feb 19 '23 at 12:49
  • OH yes I always forgot to change the upper call. Thanks now its working. – Dot Feb 19 '23 at 12:59