1

I have a base class Student(), with two derived classes GradStudent() and UndergradStudent().

The base class has a function called getInfo(), the two derived classes have their own getInfo() functions.

The assignment is to create an array of student and store an object of each class in that array. I'm then to call getInfo() from each (Using the base class function's version for each), then call the getInfo() function from the two derived classes.

For the life of me I can't figure out how to do this. Here's what I have so far:

(I guess I should mention here, I cannot modify the base class)

    Student *classRoom[3];

    Student base ( "Jim", "Bean", 1111 );
    classRoom[0] = &base;

    GradStudent test ( "Jack", "Daniels", 1234, 'M', "Art" );
    classRoom[1] = &test;

    UndergradStudent ust1 ( "Johnny", "Walker", 1235, 1 );
    classRoom[2] = &ust1;

    cout << classRoom[1]->getInfo();

Can anyone point me in the right direction? I will say that the instructions specifically it has to be an array, so no vector solutions please (Still not familiar with them anyway).

6
  • That doesn't work? It looks like it should. What's the problem? (although doing it that way is silly) Commented Feb 14, 2013 at 10:23
  • 4
    As long as getInfo is virtual -- which it should be, since it's in the base class you cannot change -- this should work. What's the problem exactly? Commented Feb 14, 2013 at 10:24
  • 1
    Show us the class definitions from Student, GradStudent and UndergradeStudent, and specify the issue you have with your code Commented Feb 14, 2013 at 10:25
  • You say "I'm then to call getInfo() from each (Using the base class function's version for each), then call the getInfo() function from the two derived classes." - do you really mean that you need to call Student's getInfo() on your GradStudent instance? Commented Feb 14, 2013 at 10:29
  • The above code is working, but I can only call getinfo() from the Student (base) class. No student is not virtual. And I cannot change that. Commented Feb 14, 2013 at 10:42

3 Answers 3

2

If you cannot modify even the derived classes, it's hard to call GetInfo on them not knowing, that they are of specific type. Maybe you are required to use direct solution:

GradStudent gradStudent;
cout << gradStudent.GetInfo();

Or you can try to check, if a student is of specified derived class, but IMO it's extremely ugly and dangerous (in terms of extending the code):

for (int i = 0; i < 3; i++)
{
    GradStudent * gs = dynamic_cast<GradStudent *>(classRoom[i]);
    if (gs != nullptr)
        cout << gs->GetInfo();
    else
    {
        UndergradStudent * ugs = dynamic_cast<UndergradStudent *>(classRoom[i]);
        if (ugs != nullptr)
            cout << ugs->GetInfo();
        else
            cout << classRoom[i]->GetInfo();
    }
}

I have to say, that polymorphism is created specifically to handle situations like this and GetInfo not being virtual in base class is serious architectural flaw.

Additionally: if you are playing with pointers, avoid retreiving addresses to local variables. That may be dangerous. Instead, allocate and deallocate the memory manually:

classRoom[0] = new Student;
classRoom[1] = new GradStudent;
classRoom[2] = new UndergradStudent;

// Process data

for (int i = 0; i < 3; i++)
    delete classRoom[i];

On the margin: I hate tasks like: Do X without using Y (where Y is specifically designed to solve X).


Edit: (in response to comments)

You asked, how virtual function would resolve the problem. Suppose for a moment, that Student::GetInfo is virtual. Let's analyse the following pieces of code:

Student * student = new Student;
student->GetInfo(); // Student::GetInfo is called

GradStudent * gradStudent = new GradStudent;
gradStudent->GetInfo(); // GradStudent::GetInfo is called

Nothing suprising, for now.

Student * student = new GradStudent;
student->GetInfo();
// if Student::GetInfo is virtual, GradStudent::GetInfo is called here
// if Student::GetInfo is not virtual, Student::GetInfo is called here

Now read carefully. If Student::GetInfo is virtual and is implemented in GradStudent class, GradStudent::GetInfo will be called, despite fact, that it is called on Student variable. However, if Student::GetInfo is not virtual, in previous case, Student::GetInfo will be called. This is basically how virtual functions work.

In your case, you have an array of Student * variables - you don't exactly know, whether they are Students, GradStudents or UndergradStudents. Since your Student::GetInfo is not virtual, calling this method on these variables will always result in calling Student::GetInfo, regardless of their actual type.

In such case the only solution I can think of is trying to guess, which class actually they are:

Student * student = new UndergradStudent;

Student * s = student; // Ok
GradStudent * gs = dynamic_cast<GradStudent *>(student); // Not true, will return NULL/nullptr
UndergradStudent * ugs = dynamic_cast<UndergradStudent *>(student); // Ok

This way you can return to the original type and call GetInfo of the actual variable type.

Note though, that this is an ugly solution and this kind of problems is solved by virtual functions.

The C++ FAQ is a good place to read further about virtual functions.

Sign up to request clarification or add additional context in comments.

3 Comments

Feel my pain. Half the questions on my exams are of the "Let me make the most awkward, horribly designed code and have you read it." And all of my assignments are exactly as you describe it. Quite frankly I hate pointers and avoid them like the plague but..
Cheer up, when I was studying, once on one big colloquium I got a source code with usage of unassigned variable. That was the funniest colloquium and the only one when I got like 110% available points :) Good luck with your exams!
So, you have no idea how you would differentiate a call between the getInfo() from the base class, and the getInfo() from it's actual class? How exactly does virtual fix things (And if too much to explain, could you point me in the right direction?)
0

If the getInfo() member function is not virtual, the first part of your assignment is to iterate on your array and call getInfo() on each of the instances.

For the second part, you will have to downcast the instance of the derived class into their real type in order to call the actual member function of the derived class.

Also I recommend you fill your array in the following way :

classRoom[0] = new Student( "Jim", "Bean", 1111 );
classRoom[1] = new GradStudent( "Jack", "Daniels", 1234, 'M', "Art" );
classRoom[2] = new UndergradStudent ( "Johnny", "Walker", 1235, 1 );

Don't forget to delete them at the end of your program.

3 Comments

I actually was trying to do it that way, but the compiler threw a fit because I have destructors.
Why would it throw a fit because you have destructors?
huh. Just tried it again and it worked. I guess I changed something since the last time I tried it (Its late...Im not thinking well). Thnaks!
0

I'm a little confused by the question, but this is what I get from it:

Iterate through each element in classRoom, calling getInfo() on each element. Then output the result of test.getInfo() and ust1.getInfo().

If that is correct, I think what the teacher may be trying to point out is that if the object on which getInfo() is being called is of one of the derived class types (GradStudent or UndergradStudent), even though the pointer to the object is of type Student*, the derived classes version of getInfo() will always be called.

This is because even though you are calling getInfo() on a Student*, getInfo() will bind to the derived classes implementation at run-time (because getInfo() is virtual).

1 Comment

Actually he's telling me to use the same array element from both getinfo() functions

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.