Lecture 28 - Nov 16, 2023
Summary
In this lecture, we continue our discussion on inheritance, data protection within a derived classes and pointers to derived classes.
Last lecture
Inheritance.
Today
Inheritance continuation.
We inherit the attributes from Person.
We do not inherit constructors.
If we create a new setName(), it will overwrite the previous one.
In Person.h:
#include <iostream>
using namespace std;
class Person {
private:
string name;
int age;
public:
Person() {
name = "";
age = 0;
}
Person(string n, int a) {
name = n;
age = a;
}
void setName(string n) { name = n; }
void print() {
cout << "Name: " << name << endl;
cout << "Age: " << age << endl;
}
};In Student.h:
#include <iostream>
using namespace std;
class Student : public Person {
private:
int ID;
// age and name are innaccessible
// we don't inherit constructors of Person
public:
Student() { ID = 0; }
// setName is inherited
void setNameID(string n, int d = 0) {
Person::setName(n);
ID = d;
}
// cancel/overwrite the print function inherited from Person
// we write our own
void print() {
// I can't access age and name
Person::print();
cout << "ID: " << ID << endl;
}
~Student() { cout << "Student destructor" << endl; }
};In main.cpp:
#include "Person.h"
#include "Student.h"
using namespace std;
int main() {
Person p("Joe", 23);
Student s; // 2 constructors are called
// 1st is Person() default constructor
// 2nd is Student() default constructor
p.setName("Joseph");
p.print(); // print name and age
s.setNameID("Ryan"); // setNameID is inherited from Person
s.print(); // we invoke print on Student object, hence we call print of
// Student, not of person
s.setNameID("Marina", 125);
s.print();
return 0;
}Inheritance versus membership
Inheritance
Inheritance represents an “is-a” relationship.
Example: Student is a Person, as Student inherits from Person.
class Person {
...
};
class Student : public Person {
...
};
Student s;
s.SetName();
// s is Student
// s is PersonMembership
Membership represents a “has-a” relationship.
Example: Student has a member Person p.
class Student {
private:
Person p;
};
Student s;
// s is Student
// s is NOT personAccess different constructors
What if I want to call a different Person constructor when I create a Student object?
class Student : public Person {
private:
int ID;
public:
Student() { ID = 0; }
// or
// Student() : ID(0);
// call the 2nd constructor in Person
// between fun() and {, the space allows an initializer's list
Student(string n, int a, int d) : Person(n,a) {
ID = d;
}
};
int main() {
// 1. Person(n,a)
// 2. Student(n,a,d)
Student s("Armaan", 20, 354);
}Data protection
protecteddata and function members are inherited and accessible to derived classes but not to all classes (somewhere between public and private).
class Person {
protected:
int age;
string name;
};
class Student : public Person {
private:
int ID;
public:
Student(string n, int a, int d) {
Person::name = n;
Person::age = a;
ID = d;
}
};Important. We do not inherit
- Constructors: You can call them.
- Copy constructors
- Operator equal
- Destructors
2-4: You can create derived’s own version of them.
int main() {
Student s;
Person p;
p = s; // => p.operator=(s)
// Person& operator=(Person& rhs) { ... }
s = p; // => s.operator=(p) - LHS is student, RHS is person => ERROR
}Very important. student is a Person and Student. person is a Person only.
Student* s1;
Person* p1;
p1 = &s;p1 pointer can be used to access Person members which also exist in Student s.
p1->setName("Selim"); // calls setName of Person
p1->print(); // calls print of Person
// p1->setNameID(); // error, because setNameID is not a member of Persons1 pointer cannot access all Student members as not all of them exist in Person (base class).
// s1 = &p; // error