Benny
Benny

Reputation: 498

Unclear syntax in the constructor

I'm student and we get this class as an example for some topic we learn:

class Student {
private:
static int maxGrade;
static Student* bestStudent;

public:
const int m_grade; 
static int nofStudents;
Student(int grade = maxGrade) :m_grade(grade) {
    if (grade > maxGrade) {
        maxGrade = grade;
        bestStudent = this;
    }
    nofStudents++;
}
Student(const Student& std) : m_grade(std.m_grade) {
    nofStudents++;
}

    ~Student() {
    if (bestStudent == this) {
        maxGrade = 0;
        bestStudent = NULL;
    }
    nofStudents--;
}
void Print()const { cout << "Grade = " << m_grade << endl; }
};

int main()
{
Student Rafi;
Student Moshe(97);
Student Avi(89);
return 0;
}

I can't understand how the constructor of class Student works even after I have debugged it and I see the process, I truely didn't understand the logic of this line:

Student(int grade = maxGrade) :m_grade(grade){...} 

for some reason that I didn't understand, in evrey call to the constructor, grade holds the value of the last call altough there is "int grade = maxGrade".

any explenations to this syntax will be great, thanks alot.

Upvotes: 0

Views: 131

Answers (3)

Overbyte
Overbyte

Reputation: 136

You referenced the line: Student(int grade = maxGrade) :m_grade(grade){...}

It sounded like from your comments that the parameter in the constructor was the source of confusion, probably relating to the included equal sign. This specifies a default value to use for grade in the event that none is provided. This has the effect of allowing users of your class to call that constructor with no parameters. Note that you are only allowed to specify default values for the last parameter (in the case more than 1 are present).

In your case maxGrade is a static variable so there is only one instance that all Student objects refer to. As you construct Student objects, this value is subject to change according to the logic in your constructor body. If you build the Student with the best grade first, you won't see this maxGrade change. It will be more obvious what is happening if you build some Students with lower grades first, going progressively higher each time.

Upvotes: 0

txtechhelp
txtechhelp

Reputation: 6752

I truely didn't understand the logic of this line:

Student(int grade = maxGrade) :m_grade(grade){...}

In C++, you can have a function that takes an argument, for example:

static void print_int(int val)
{
    std::cout << "value = " << val << std::endl;
}

You can also specify that the function not take any arguments, for example:

static void print_int()
{
    std::cout << "value = NOTHING HERE" << std::endl;
}

In this way, I can call print_int with, or without a value, like so:

print_int();
print_int(42);

output:
value = NOTHING HERE
value = 42

In C++, we can also specify functions that have what are known as default arguments, so that I can write just one function to handle a scenario like above, for example:

static void print_int(int val = 314159)
{
    std::cout << "value = " << val << std::endl;
}

So just as above, I can then call print_int with, or without a value, like so:

print_int();
print_int(42);

output:
value = 314159
value = 42

Given this, we can then look at your Student constructor1 that you are confused on:

Student(int grade = maxGrade)

And ascertain that if you were to create a Student object and did not give it an argument (i.e. the grade), then the default value for that student's grade would be whatever the current highest grade is2, for example:

Student alpha(50);  // current max grade set to 50
Student beta;       // max grade still 50, set 'beta'
Student gamma(42);  // 42 < 50, max grade unchanged
Student lambda(96); // 96 > 50, max grade now 96
Student zeta;       // max grade still 96, set 'zeta'

alpha.Print();  // Grade = 50
beta.Print();   // Grade = 50
gamma.Print();  // Grade = 42
lambda.Print(); // Grade = 96
zeta.Print();   // Grade = 96

Based on your use of static members, I don't want to assume, but it appears that you understand that concept, so the constructor is the same as saying

Student(int grade = Student::maxGrade)

Thus, if Student::maxGrade is defined as 0, then the above example works. If, however, the maxGrade is set to something other than 0 before creating any Student objects, (e.g. int Student::maxGrade = 50;), then the above example changes:

// defined somewhere in your code (e.g. above main)
int Student::maxGrade = 50;

// elsewhere in code (e.g. main)
Student alpha(42); // 42 < 50, max grade unchanged
Student beta;      // max grade 50, set 'beta' to 50
Student gamma(96); // 96 > 50, max grade now 96
Student lambda;    // max grade 96, set 'lambda'

alpha.Print();  // Grade = 42
beta.Print();   // Grade = 50
gamma.Print();  // Grade = 96
lambda.Print(); // Grade = 96

As to the rest of the syntax, the part after the colon (:), on a constructor that is known as the member initialization list, you can think of that syntax similar to this:

// with initialization list
Student(int grade = maxGrade) : m_grade(grade)
{
    ...
}

// without initialization list
Student(int grade = maxGrade)
{
    this->m_grade = grade;
    ...
}

The link above is more technical, but this answer has good explanation on "why" use a member initialization list, as well, your professor might be able to answer why, if you have not already gone over that.

Just to add, you could also write your Student class to have two constructors that give the same effect of the one in question, for example:

Student() : m_grade(maxGrade) { ... }
Student(int grade) : m_grade(grade) { ... }

If that gives any clarity3 to understanding the syntax.

I hope that can help.

1: Hopefully your professor has gone over "the rule of 3/5/0" with you.
2: That's an odd way to grade :/
3: And depending on how you wanted your code to work, you might want to mark the Student(int) constructor as explicit, e.g. explicit Student(int)

Upvotes: 4

davmac
davmac

Reputation: 20631

If you "assign" a parameter in a function or constructor declaration a value, you are specifying a default value for when no other is supplied when the function/constructor is called.

If another value is supplied at the call site, that value will be assigned to the parameter instead.

In your example:

Student Rafi;
Student Moshe(97);
Student Avi(89);

The first call to the constructor will have the grade parameter set to the current value of maxGrade, because no value is supplied. The second will have grade set to 97 and the third will have it set to 89.

Upvotes: 1

Related Questions