Multiple Inheritance and Polymorphism

So I've done most of the work but I don't know how to do part 4.


1.Create a new class StaffST which has Staff and Student as base classes. StaffSt has an additional attribute (int) credithours.

2. Create the virtual string function whatami() for the Person class. The function returns the type of class - Person, Faculty, Staff, etc. Note that you must create a separate function for each derivedclass.

3.Write a string function classify which accepts a Person pointer variable as an argument and returns the output from whatami().

4.Write a test main program that creates a vector of pointers to Person. Creat a Person, Student, Employee, Faculty, Staff and StaffST object and add pointers to these objects to your vector. Now use the function classify to output the type of each object from the vector pointers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352

#ifndef PERSON_H
#define PERSON_H
#include <string>

using namespace std;

class Person
{
public:
Person ();
Person (string n, string a, string t, string e);
string getName();
string getAddress();
string getTelephonenumber();
string getEmailaddress();
virtual string whatami();

private:

string name;
string address;
string telephone;
string email;
};
#endif

#include "Person.h"
#include <string>
using namespace std;


Person::Person (string n, string a, string t, string e)
{
 name = n;
 address = a;
 telephone = t;
 email = e;
}

string Person::getName()
{
return name;
}

string Person::getAddress()
{
return address;
}

string Person::getTelephonenumber()
{
return telephone;
}

string Person::getEmailaddress()
{
return email;
}

string Person::whatami()
{
return "Person";
}

#include "Student.h"
#include <string>
using namespace std;

Student::Student(string n, string a, string t, string e, string yr): Person
(n, a, t, e)
{
	year = yr;
}

string Student::getYear()
{
	return year;
}


string Student::whatami()
{
 return "Student";
}

#ifndef STUDENT_H
#define STUDENT_H
#include <string>
#include "Person.h"

  using namespace std;
 
  class Student: public Person
    {
    public:
        Student(string n, string a, string t, string e, string yr);
	string getYear();
	string whatami();
    private:
	string year;
    }; 
#endif

#include "Employee.h"
#include <string>
using namespace std;
 
Employee::Employee(string n, string a, string t, string e, string off, string slry, string hdate): Person(n , a , t, e)

{
office= off;
salary = slry;
hiredate= hdate;
}

string Employee::getOffice()
{
return office;
}

string Employee::getSalary()
{
return salary;
}

string Employee::getHiredate()
{
return hiredate;
}

string Employee::whatami()
{
 return "Employee";
}

#ifndef EMPLOYEE_H
#define EMPLOYEE_H
#include <string>
#include "Person.h"
  using namespace std;
 
  class Employee: public Person
    {
    public:
       
        Employee(string n, string a, string t, string e, string off, string slry, string hdate);
        string getOffice();
        string getSalary();
        string getHiredate();
	virtual string whatami();
    private:
        string office;
        string salary;
        string hiredate;
    }; 
#endif

#include "Faculty.h"
#include <string>
using namespace std;
 
Faculty::Faculty(string n, string a, string t, string e, string off, string slry, string hdate, string rank, string stat):
	Employee(n, a, t, e, off, slry, hdate)

{
frank = rank;
fstatus = stat;
}

string Faculty::getRank()
{
return frank;
}

string Faculty::getFstatus()
{
return fstatus;
}

string Faculty::whatami()
{
 return "Faculty";
}

#ifndef FACULTY_H
#define FACULTY_H
#include <string>
#include "Employee.h"
using namespace std;

class Faculty: public Employee
{
public:
	Faculty(string n, string a, string t, string e, string off, string slry, string hdate,string rank, string stat); 
	string getRank();
	string getFstatus();
	virtual string whatami();
private:
	string frank;
	string fstatus;

};
#endif

#ifndef STAFF_H
#define STAFF_H
#include <string>
#include "Employee.h"
using namespace std;

class Staff: public Employee
{
public:
	Staff(string n, string a, string t, string e, string off, string slry, string hdate, string title);
	string getJobtitle();
	virtual string whatami();

private:

string jobtitle;

};
#endif

#include "Staff.h"
#include <string>
using namespace std;
 
Staff::Staff(string n, string a, string t, string e, string off, string slry, string hdate, string title):
	Employee(n, a, t, e, off, slry, hdate)
{
	jobtitle = title;
}

string Staff::getJobtitle()
{
	return jobtitle;
}

string Staff::whatami()
{
 return "Staff";
}

#ifndef STAFFST_H
#define STAFFST_H
#include "Person.h"
#include "Student.h"
#include "Employee.h"
#include "Staff.h"
#include <string>
using namespace std;



class Staffst: public Student, public Staff
{
public:
	Staffst(string n, string a, string t, string e, string off, string slry, string hdate,string rank, string stat, int c); 
	virtual string whatami();
	int getCredithours();

private:
	int credith;

};
#endif

#include "Staffst.h"
#include <string>
using namespace std;

Staffst::Staffst(string n, string a, string t, string e, string off, string slry, string hdate,string rank, string stat, int c): 
Student(n, a, t, e, yr), Staff(n, a, t, e, off, slry, hdate, title)
{
	credith = c;
}

int Staffst::getCredithours()
{
return credith;
}


string Staffst::whatami()
{
 return "Staffst";
}

#include "Person.h"
#include "Student.h"
#include "Employee.h"
#include "Faculty.h"
#include "Staff.h"
#include "Staffst.h"
#include <iostream>
#include <string>
#include <vector>
using namespace std;

string classify(Person *p) 
{
  return p->whatami(); 
}


int main()
{ 
   vector<Person*> v;
   v.push_back(new Person("John Adams","Boston","617-555-0000","john@adams.com"));
   v.push_back(new Student("John Quincy Adams","Boston","617-555-0000","johnq@adams.com","senior"));
   v.push_back(new Faculty("John Doe", "123 Citrus Dr.", " 909-255-0002","Jdoe@email.com", " Room 354", "$46,000/yr", "January 24,2011", "Professor", "Tenured"));
   v.push_back(new Employee("John Smith", "123 coyote Dr.", " 909-255-0001", "john@yahoo.com", "Jack Brown 385", "$50,000/yr", "June 13, 2005"));
   v.push_back(new Staff("Samuel Adams","Boston","617-555-BEER","sam@adams.com","brewhouse 1","$25,000"," 5-3-08","Brewer"));
   v.push_back(new StaffST("Samuel Smith","Boston","617-555-BEER","samsmith@adams.com","brewhouse 5","9-15-1774","Taster","junior",100));


  for (int i=0; i<v.size(); i++)
{
cout << classify(v[i]) << endl;
cout << "Name: " << v[i]->getName() << endl;
cout << "Address: " << v[i]->getAddress() << endl;
cout << "Phone: " << v[i]->getTelephonenumber() << endl;
cout << "Email: " << v[i]->getEmailaddress() << endl;
}
if(classify(v[i]) == "Student")
{
cout << "Year: " << v[i]->getYear() << endl;
}
if(classify(v[i]) == "Employee")
{
cout << "Office: " << v[i]->getOffice() << endl;
cout << "Salary: " << v[i]->getSalary() << endl;
cout << "Hire Date: " << v[i]->getHiredate() << endl;
}
if(classify(v[i]) == "Staff")
{
cout << "Job title: " <<v[i]->getJobtitle() << endl;
}
if(classify(v[i]) == "Faculty")
{
cout << "Rank: " << v[i]->getRank() << endl;
cout << "Faculty status: " << v[i]->getFstatus() << endl;
}
if(classify(v[i]) == "StaffST")
{
cout << "Credit Hours: " << v[i]->getCredithours() << endl;
}

return 1;
} 
Last edited on
when I compile I get these errors.

Main.cpp: In function ‘int main()’:
Main.cpp:20:127: error: no matching function for call to ‘Staff::Staff(const char [13], const char [7], const char [13], const char [14], const char [12], int, const char [13], const char [7], int)’
Main.cpp:20:127: note: candidates are:
In file included from Main.cpp:5:0:
Staff.h:11:2: note: Staff::Staff(std::string, std::string, std::string, std::string, std::string, std::string, std::string, std::string)
Staff.h:11:2: note: candidate expects 8 arguments, 9 provided
Staff.h:8:7: note: Staff::Staff(const Staff&)
Staff.h:8:7: note: candidate expects 1 argument, 9 provided
Main.cpp:21:20: error: expected type-specifier before ‘StaffST’
Main.cpp:21:20: error: expected ‘)’ before ‘StaffST’
Main.cpp:21:136: error: no matching function for call to ‘std::vector<Person*>::push_back(int*)’
Main.cpp:21:136: note: candidate is:
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/vector:65:0,
from Main.cpp:9:
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:881:7: note: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = Person*; _Alloc = std::allocator<Person*>; std::vector<_Tp, _Alloc>::value_type = Person*]
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:881:7: note: no known conversion for argument 1 from ‘int*’ to ‘Person* const&’
Main.cpp:27:22: error: ‘classify’ was not declared in this scope
Main.cpp:35:27: error: ‘class Person’ has no member named ‘getYear’
Main.cpp:39:29: error: ‘class Person’ has no member named ‘getOffice’
Main.cpp:40:29: error: ‘class Person’ has no member named ‘getSalary’
Main.cpp:41:32: error: ‘class Person’ has no member named ‘getHiredate’
Main.cpp:43:31: error: ‘class Person’ has no member named ‘getJobtitle’
Main.cpp:47:27: error: ‘class Person’ has no member named ‘getRank’
Main.cpp:48:37: error: ‘class Person’ has no member named ‘getFstatus’
Main.cpp:52:35: error: ‘class Person’ has no member named ‘getCredithours’
Main.cpp:59:1: error: expected ‘}’ at end of input
whatami() must return a string so return a string:
1
2
3
4
string Employee::whatami()
{
 return "Employee"; // simple, isn't it?
}


Write a string function classify which accepts a Person pointer variable as an argument and returns the output from whatami().

just read what the assignment says;

1
2
3
4
5
//write a string function -> must return a string
string classify(Person *p)  // ...  which accepts a Person pointer variable as an argument
{
  return p->whatami(); // .. and returns the output from whatami()
}
1) You're missing a few includes:
1
2
3
#include <string>
#include <vector>
#include <iostream> 


2) All your whatami functions are incorrect. They are all declared as string functions, so you must return a string. You're trying to return a class. Example:
1
2
3
string Student::whatami()
{ return "Student";
}


3) Line 204. The implementation of your constructor doesn't match the declaration on line 195.

4) Line 205. Calls to the base class constructors are using undefined variables.

5) Line 207. credithours is undefined. i.e. your private variable has a different name.

6) Line 210. The type of the implementation (string) doesn't match the type of the declaration (int).

7) Line 216. StaffSt doesn't have a declaration for function whatami.

8) Line 235. There's no implementation of the classify function.

9) Lines 243-260. You're referencing v[i] which is a reference to a Person object, but the Person class has no function getyear(). Same thing for the other getters. You need to do a cast to a pointer of the correct type.




Edited out. Will be using first post
Last edited on
I'm a little confused by the code you posted. Lines 20-28 is not a complete class declaration. I'm assuming you dropped the closing };

Lines 39-42 classify appears to be in the middle of main(). You can't put one function inside another. classify should go before main.

For my item 9, you're going to need to do a dynamic_cast
See http://www.cplusplus.com/doc/tutorial/typecasting/
I've updated my code and I get this when I try to compile. I really don't know how to go about doing part 4.

Main.cpp: In function \u2018int main()\u2019:
Main.cpp:31: error: no matching function for call to \u2018Staff::Staff(const char [13], const char [7], const char [13], const char [14], const char [12], const char [13], const char [7])\u2019
Staff.h:10: note: candidates are: Staff::Staff(std::string, std::string, std::string, std::string, std::string, std::string, std::string, std::string)
Staff.h:8: note: Staff::Staff(const Staff&)
Main.cpp:32: error: expected type-specifier before \u2018StaffST\u2019
Main.cpp:32: error: expected \u2018)\u2019 before \u2018StaffST\u2019
Main.cpp:32: error: no matching function for call to \u2018std::vector<Person*, std::allocator<Person*> >::push_back(int*)\u2019
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_vector.h:733: note: candidates are: void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = Person*, _Alloc = std::allocator<Person*>]
Main.cpp:43: error: name lookup of \u2018i\u2019 changed for ISO \u2018for\u2019 scoping
Main.cpp:43: note: (if you use \u2018-fpermissive\u2019 G++ will accept your code)
Main.cpp:45: error: \u2018class Person\u2019 has no member named \u2018getYear\u2019
Main.cpp:49: error: \u2018class Person\u2019 has no member named \u2018getOffice\u2019
Main.cpp:50: error: \u2018class Person\u2019 has no member named \u2018getSalary\u2019
Main.cpp:51: error: \u2018class Person\u2019 has no member named \u2018getHiredate\u2019
Main.cpp:55: error: \u2018class Person\u2019 has no member named \u2018getJobtitle\u2019
Main.cpp:59: error: \u2018class Person\u2019 has no member named \u2018getRank\u2019
Main.cpp:60: error: \u2018class Person\u2019 has no member named \u2018getFstatus\u2019
Main.cpp:64: error: \u2018class Person\u2019 has no member named \u2018getCredithours\u2019
Indent your code properly.

> `class Person' has no member named `getYear'
Well, it hasn't. You can't ask a Person about its year, you need to ask a Student.

> error: no matching function for call to `Staff::Staff(...)'
note: candidate expects 8 arguments, 7 provided.
Try to make your constructor more clear (by instance you could ask for an adress, instead of several strings that represent it)
Well I fixed that second thing you told me. But on that first one I thought I was only asking student for the year. I'm not supposed to include the year for the person. I get this when compiling now. I don't know how to only ask student for the year then proceed to ask the other objects for the same items+more.

Main.cpp: In function \u2018int main()\u2019:
Main.cpp:32: error: expected type-specifier before \u2018StaffST\u2019
Main.cpp:32: error: expected \u2018)\u2019 before \u2018StaffST\u2019
Main.cpp:32: error: no matching function for call to \u2018std::vector<Person*, std::allocator<Person*> >::push_back(int*)\u2019
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_vector.h:733: note: candidates are: void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = Person*, _Alloc = std::allocator<Person*>]
Main.cpp:43: error: name lookup of \u2018i\u2019 changed for ISO \u2018for\u2019 scoping
Main.cpp:43: note: (if you use \u2018-fpermissive\u2019 G++ will accept your code)
Main.cpp:45: error: \u2018class Person\u2019 has no member named \u2018getYear\u2019
Main.cpp:49: error: \u2018class Person\u2019 has no member named \u2018getOffice\u2019
Main.cpp:50: error: \u2018class Person\u2019 has no member named \u2018getSalary\u2019
Main.cpp:51: error: \u2018class Person\u2019 has no member named \u2018getHiredate\u2019
Main.cpp:55: error: \u2018class Person\u2019 has no member named \u2018getJobtitle\u2019
Main.cpp:59: error: \u2018class Person\u2019 has no member named \u2018getRank\u2019
Main.cpp:60: error: \u2018class Person\u2019 has no member named \u2018getFstatus\u2019
Main.cpp:64: error: \u2018class Person\u2019 has no member named \u2018getCredithours\u2019
Did you research dynamic_cast as you said you were going to do?

As I said beofre, you need to cast your person pointer to one of the correct type.
For example, a Student has a year member and a getYear function, but a person doesn't. This is what polymorphism inheritence is all about.
Last edited on
no... that would be no using polymorphism.

1
2
3
4
5
6
7
8
9
10
11
12
for(size_t K=0; K<v.size(); ++K)
   v[K]->print();


virtual void Person::print() const{
   cout << name << '\n' << address << '\n' << phone << '\n' << email << '\n';
}

virtual void Student::print() const{
   Person::print();
   cout << year << '\n';
}
@ne555 - You're right of course. Wasn't thinking when I posted that. I've corrected the post.
I looked into dynamic casting but I don't believe that's what our professor wanted us to do. He never mentioned this before.

@ne555 with your code how would I accomplish this?

Write a test main program that creates a vector of pointers to Person. Create a Person, Student, Employee, Faculty, Staff and StaffST object and add pointers to these objects to your vector. Now use the function classify to output the type of each object from the vector pointers.

I'm really confused as to how to do this. We really didn't cover polymorphism much. I'm pretty much asking for a spoon feed here with an explanation on what's going on.
We could do this one of two ways.

1) Using inheritance and a dynamic cast.
1
2
3
4
5
6
if(classify(v[i]) == "Student")
{  Student *   student;

    student = dynamic_cast<Student *> (&vector[i]);
    cout << "Year: " << student->getYear() << endl;
}

We create a pointer of type Student. Since we know from the if statement that v[i] is a student, we can downcast &v[i] (pointer to a person) to become a pointer to a student. Then we can use the student pointer to refer to members to of the student class. I'm sure you can extend this to the other derived types.

2) We can use polymorphism. For this we need to define a virtual function in Person.
1
2
3
4
5
6
7
8
9
10
class Person
{
public: 
  virtual Person * getPointer ();
...
};

Person * Person::getPointer ()
{  return this;
}


You'll also need to define getPointer in each derived class.
1
2
3
4
5
6
7
8
9
10
class Student
{
public: 
  virtual Student * getPointer ();
...
};

Student * Student::getPointer ()
{  return this;
}


Now in your code:
1
2
3
4
5
6
7
 
if(classify(v[i]) == "Student")
{  Student *  student;

    student = v[i].getPointer();
    cout << "Year: " << student->getYear() << endl;
}

Because of polymorphisim, when Person's getPointer() function is called it is really Student's getPointer() function that is called due to the overloaded function.
Now you can reference any members of Student through the pointer. You'll need to extend this to each of the derived classes.

If your instructor has been teaching polymorphism and virtual functions and has not covered dynamic_cast, then #2 is the way you want to go.
1
2
3
Person * Person::getPointer (){
   return this;
}
what a pointless function.

1
2
3
std::vector< Person* > v;
//...
Student *student = v[K]->getPointer(); //error: invalid conversion from `Person*' to `Student*' 
The compiler cannot determine the type of `*v[K]'


> Now use the function classify to output the type of each object from the vector pointers.
1
2
for( size_t K=0; K<v.size(); ++K)
   std::cout << v[K]->whatami() << '\n';
Last edited on
@ne555 - okay, I didn't compile that before I posted it. What I was trying to do was to show an example of using an overloaded function to assign the pointer to the proper type rather than a dynamic_cast, but I see now that didn't work. I'm surprised the compiler wasn't able to figure out the correct overload.

Now use the function classify to output the type of each object from the vector pointers.

That doesn't solve the OP's issue of addressing member function of derived classes.
> I'm surprised the compiler wasn't able to figure out the correct overload.
¿how could it? the type is resolved at runtime.
Topic archived. No new replies allowed.