// student.cpp - Script 9.7

#include <iostream>

#include <string>

// Declare the Person class.
class Person {
public:
Person(std::string theName);

void introduce();

protected:
std::string name;
};

// Declare the Teacher class.
// Teacher inherits Person.
class Teacher: public Person {
public:
Teacher(std::string theName, std::string theClass);

void teach();
void introduce();

protected:
std::string clazz;
};

// Declare the Student class.
// Student inherits Person.
class Student: public Person {
public:
Student(std::string theName, std::string theClass);

void attendClass();
void introduce();

protected:
std::string clazz;
};

// Declare the TeachingStudent class.
// TeachingStudent inherits both Student and Teacher.
class TeachingStudent : public Student, public Teacher {
public:

// Constructor.
TeachingStudent(
std::string theName,
std::string classTeaching,
std::string classAttending);

void introduce();
};

// Define the methods.
Person::Person(std::string theName) {
name = theName;
}

void Person::introduce() {
     std::cout << "Hi I'm " << name << "\n";
     }

Teacher::Teacher(std::string theName, std::string theClass)
: Person(theName) {
clazz = theClass;
}

void Teacher::teach() {
std::cout << name << " teaches ";
std::cout << "'" << clazz << ";.\n";
}

void Teacher::introduce() {
std::cout << "Hi I'm " <<name << ", and I teach '" << clazz << "'\n";
}

Student::Student(std::string theName, std::string theClass): Person(theName) {
clazz = theClass;
}

void Student::attendClass() {
std::cout << name << " attends ";
std::cout << "'" << clazz << "'.\n";
}

void Student::introduce() {
std::cout << "Hi I'm " << name << ", and I study '" << clazz << "'\n";
}

// TeachingStudent's constructor must invoke
// the constructors of all base classes!
TeachingStudent::TeachingStudent(
std::string theName,
std::string classTeaching,
std::string classAttending)
: Teacher(theName, classTeaching),
Student(theName, classAttending)
{
}

void TeachingStudent::introduce() {
// Because TeachingStudent inherits two copies of Person's
// attributes (one from Teacher and one from Student),
// we must tell the compiler which copy to use.
std::cout << "Hi I'm " << Student::name << ". I teach '" << Teacher::clazz << ";, ";
std::cout << "and I study '" << Student::clazz << ";.\n";
}


int main() {

// Create the objects.
Teacher teacher("Jim", "C++ 101");
Student student("Bob", "C++ 101");
TeachingStudent teachingStudent("Mike", "C++ 101", "Advanced C++");

// Make them do things.
teacher.introduce();
teacher.teach();
student.introduce();
student.attendClass();
teachingStudent.introduce();
teachingStudent.teach();
teachingStudent.attendClass();

std::cout << "Press Enter or Return to continue.";
std::cin.get();
return 0;
}

I'm having trouble understanding this code. Can anybody help? In particular having trouble with this part:

TeachingStudent:: TeachingStudent(
std::string theName,
std::string classTeaching,
std::string classAttending)
: Teacher(theName, classTeaching), Student(theName, classAttending)

I don't understand why the parameters are different in the Teacher and Student implementation to the implementation of TeachingStudent i.e (theName, classTeaching) instead of (theName, theClass)- Where the constructors of the base classes are invoked. I also presume Person(theName) isn't called because it's inherited from Student and Teacher?

also

void TeachingStudent::introduce() {
// Because TeachingStudent inherits two copies of Person's
// attributes (one from Teacher and one from Student),
// we must tell the compiler which copy to use.
std::cout << "Hi I'm " << Student::name << ". I teach '" << Teacher::clazz << "', ";
std::cout << "and I study '"<< Student::clazz << "'.\n";

std::cout << "Hi I'm " << Student::name << ". I teach '" << Teacher::clazz << "', ";
std::cout << "and I study '"<< Student::clazz << "'.\n";

I find this confuseing as I'm associateing Student::name with "Bob" from Student student("Bob", "C++101") Teacher::clazz with "C++ 101" from Teacher teacher("Jim", C++ 101"); and Student::clazz with "C++ 101" from Student student("Bob", "C++ 101",

An explanation as to where I'm going wrong would be much appreciated. Thanks in advance.

I don't understand why the parameters are different in the Teacher and Student implementation to the implementation of TeachingStudent i.e (theName, classTeaching) instead of (theName, theClass)- Where the constructors of the base classes are invoked. I also presume Person(theName) isn't called because it's inherited from Student and Teacher?

also

void TeachingStudent::introduce() {
// Because TeachingStudent inherits two copies of Person's
// attributes (one from Teacher and one from Student),
// we must tell the compiler which copy to use.
std::cout << "Hi I'm " << Student::name << ". I teach '" << Teacher::clazz << "', ";
std::cout << "and I study '"<< Student::clazz << "'.\n";
std::cout << "Hi I'm " << Student::name << ". I teach '" << Teacher::clazz << "', ";
std::cout << "and I study '"<< Student::clazz << "'.\n";

I find this confuseing as I'm associateing Student::name with "Bob" from Student student("Bob", "C++101") Teacher::clazz with "C++ 101" from Teacher teacher("Jim", C++ 101"); and Student::clazz with "C++ 101" from Student student("Bob", "C++ 101",

Or do the class variables std::string classTeaching, and std::string classAttending in :Teacher(theName, classTeaching), Student(theName, classAttending) take the place of std::string theClass in Teacher::Teacher(std::string theName, std::string theClass) and std::string theClass in Student:: Student(std::string theName, std::string theClass)?

An explanation as to where I'm going wrong would be much appreciated. Thanks in advance.

I find this confuseing as I'm associateing Student::name with "Bob" from Student student("Bob", "C++101") Teacher::clazz with "C++ 101" from Teacher teacher("Jim", C++ 101"); and Student::clazz with "C++ 101" from Student student("Bob", "C++ 101",

I think your confusing a class with an instance of a class (an object). The class isn't called "Bob", "Jim" or "Mike", those are the values of the name member variable of an instance of the Person class. When you do something like Teacher::clazz, you're saying to use the clazz variable inherited from the Teacher class, as opposed to the one inherited from the Student class.

Or do the class variables std::string classTeaching, and std::string classAttending in :Teacher(theName, classTeaching), Student(theName, classAttending) take the place of std::string theClass in Teacher::Teacher(std::string theName, std::string theClass) and std::string theClass in Student:: Student(std::string theName, std::string theClass)?

It just works like any other function. That is, when you call the function, it doesn't matter what you call the variable, it only matters what type it is and it's order in the arguments to the function. In this case, the constructor for Teacher expects two std::string objects and it's going to assign the first one to the name and the second one to the class (not a C++ class, the place where you go to learn type of class)

I think I understand it now!! classTeaching is assigned to theClass in the Teacher constructor which is then assigned to clazz. classTeaching is passed to the Teacher constructor but is also a part of the TeachingStudent constructor containing "C++101"
So Teacher::clazz becomes "C++ 101"

classAttending is assigned to theClass in the Student constructor which is then assigned to clazz. classAttending is passed to the Student constructor but is also a part of the TeachingStudent constructor containing "Advanced C++" So student::clazz becomes "Advanced C++"

Am I right or wrong? lol please be right.

argh confused again. Is string theName passed to the Teacher and Student constructors?.. in the same way as classTeaching classAttending are? And if so how is it passed to both constructors when the TeachingStudent constructor only has one std::string theName? Wouldn't it need two and if not why?

Ok, in your second last post, you are right! That is exactly how it goes.


As for 'theName', there are two of them. Both are inherited from Person, but one is inherited through Student and the other is inherited through Teacher. This is why you can access one via Student::theName and the other via Teacher::theName. The problem is if you try to access 'theName' directly (without the 'Student::' or 'Teacher::'), then the compiler will have a problem with that because there are two to choose from.

So, 'theName' is the same case as 'theClass' which you understood correctly. The only difference is that the two 'theName' variables (the one from Student and the one from Teacher) are initialized to the same value by passing the same string to both constructors of Student and Teacher (which each carry that string over to their base class 'Person').

At this point, it might seem odd to you that there are two 'theName' when there really only need to be one. But the compiler can't know that. There is a mechanism in C++ to tell the compiler that this is the case, and it is usually used in this kind of multiple inheritance case, and it is called virtual inheritance, you can read more on that here.

Thanks for your help and the link. So I'm guessing that there only need to be one std::string theName object in the TeachingStudent constructor and not two?
i.e not

TeachingStudent::TeachingStudent( std::string theName, std::string theName,
std::string ClassTeaching, std::string classAttending)

to pass to the Teacher and Student constructor?.. I'm guessing the compiler just assumes that there are two std::string theName objects to pass to the Student and Teacher constructor one inherited through Student and one inherited through Teacher?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.