Previous Lecture Lecture 9 Next Lecture

Lecture 9, Thu 04/30

Inheritance and Polymorphism

Inheritance

Example (Person / Student Inheritance)

// Makefile
CXX=g++

main: main.o Student.o Person.o
	${CXX} -o main -std=c++11 main.o Student.o Person.o

clean:
	rm -f *.o main
// Person.h
#ifndef PERSON_H
#define PERSON_H
class Person {
public:
	Person(std::string name, int age);
	std::string getName();
	int getAge();
	void setName(std::string name);
	void setAge(int age);
private:
	std::string name;
	int age;
};
#endif
// Student.h
#ifndef STUDENT_H
#define STUDENT_H
#include "Person.h"

class Student : public Person {
public:
	Student(std::string name, int age, int studentId);
	int getStudentId();
	void setStudentId(int id);
private:
	int studentId;
};
#endif
// Person.cpp
#include <string>
#include <iostream>
#include "Person.h"

using namespace std;

Person::Person(string name, int age) {
	cout << "Inside a Person constructor" << endl;
	this->name = name;
	this->age = age;
}

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

int Person::getAge() { return age; }

void Person::setName(string name) { this->name = name; }

void Person::setAge(int age) { this->age = age; }
// Student.cpp
#include <string>
#include <iostream>
#include "Student.h"

using namespace std;

Student::Student(string name, int age, int id) : Person(name, age){
	cout << "Inside a Student constructor" << endl;
	studentId = id;
}

int Student::getStudentId() { return studentId; }

void Student::setStudentId(int id) { studentId = id; }
// Main.cpp
#include <iostream>
#include "Student.h"
#include "Person.h"

using namespace std;

int main(){
	// Creating a Person object:
	Person p1("Chris Gaucho", 21);
	cout << "Name: " << p1.getName() << endl;
	cout << "Age: " << p1.getAge() << endl;

	cout << endl;

	// Creating a Student object
	Student s1("John Doe", 22, 12345678);
	cout << "Name: " << s1.getName() << endl;
	cout << "Age: " << s1.getAge() << endl;
	cout << "Student ID: " << s1.getStudentId() << endl;

	s1.setAge(26);
	cout << "Age: " << s1.getAge() << endl;

	return 0;
}

Note:

Note on constructors and inheritance

Redefining inherited functions

// in Student.h
std::string getName();
// in Student.cpp
string Student::getName() {
	//return "STUDENT: " + name; //ERROR, name isn’t inherited
	//cout << "Inside Student::getName()" << endl;
	//return "STUDENT: " + getName(); // ERROR Student::getName() is called.
	return "STUDENT: " + Person::getName(); // OK!
} 

Inheritance Types

Person p1("Chris Gaucho", 21);
Student s1("John Doe", 22, 12345678);

Person p2  = s1; // Legal, a student is a person
Student s2 = p1; // illegal, a person may not be a student

Memory Slicing

cout << p2.getName() << endl;
cout << p2.getAge() << endl;
cout << p2.getStudentId() << endl; // ERROR! p2 doesn’t have studentID
cout << sizeof(p1) << endl;
cout << sizeof(p2) << endl;
cout << sizeof(s1) << endl;

Pointers of base types

Person* p1 = new Person("R1", 10);
Student* s1 = new Student("JD", 21, 1234567);

// Student* s2 = p1;    // Illegal!
Person* p2 = s1;        // OK.
cout << p2->getName() << endl;
cout << p2->getAge() << endl;
//cout << p2->getStudentId() << endl; // illegal! getStudentId() is not known in Person
cout << s1->getName() << endl;
cout << s1->getAge() << endl;
cout << s1->getStudentId() << endl; // OK.

Destructors and Inheritance

Example

// in Student.h
~Student();
// in Student.cpp
Student::~Student() {
	cout << "in Student Destructor" << endl;
}
// in Person.h
~Person();
// in Person.cpp
Person::~Person() {
	cout << "in Person destructor" << endl;
}
// in main.cpp
Person* p1 = new Person("R1", 10);
Student* s1 = new Student("JD", 21, 1234567);
delete p1;
cout << "---" << endl;
delete s1;

Person* p2 = new Student("Student", 25,7654321);

// calls Person's destructor only
delete p2;

// But student object memory has not been destructed properly in this case.
// Polymorphism and virtual destructors will allows us to call
// the appropriate destructor in this scenario...