|
|
|
Lecture 24 — inheritance in C++
|
|
|
|
|
final exam topics
|
|
|
|
|
x86-64 assembly
|
|
|
|
|
integer representation
|
|
|
|
|
concurrency (next week)
|
|
|
|
|
bash
|
|
|
|
|
C
|
|
|
|
|
C++
|
|
|
|
|
exercise: bank account class
|
|
|
|
|
account.h:
class BankAccount {
public: // public interface
// constructor BankAccount(int acctnum, int initial_balance);
// methods void deposit(int howmuch); int get_balance(); int get_account();
// instance variables private: int number; int balance;
};
|
|
|
|
|
account.cpp:
#include "BankAccount.h"
// constructors BankAccount::BankAccount(int acctnum, int initial_balance){ balance = initial_balance; number = acctnum; }
// member functions
void BankAccount::deposit(int howmuch) { balance += howmuch; }
int BankAccount::get_balance() { return balance; }
int BankAccount::get_account() { return number; }
|
|
|
|
|
bank.cpp:
#include <iostream> using namespace std;
#include "BankAccount.h"
int main() { // stack allocated object BankAccount mine(17,42); cout << "my account num = " << mine.get_account() << ", balance = " << mine.get_balance() << endl;
// heap allocated object BankAccount *yours = new BankAccount(1,0); yours->deposit(1000000); cout << "your account num = " << yours->get_account() << ", balance = " << yours->get_balance() << endl; delete yours;
return 0; }
|
|
|
|
|
teaser:
|
|
|
|
|
we have a class A with methods m1 and m2
|
|
|
|
|
we have a class B that is a subclass of A that overrides methods m1 and m2
|
|
|
|
|
in the following main function, which methods are actually called?
|
|
|
|
|
int main() { A* x = new B(); x->m1(); x->m2(); }
|
|
|
|
|
answer: it depends
|
|
|
|
|
C++ lets you choose which methods will be called in which situations as part of the class definition
|
|
|
|
|
lots of control, but added complexity
|
|
|
|
|
public single inheritance
|
|
|
|
|
a base class has a set of public data and methods
|
|
|
|
|
these can be inherited by a derived class
|
|
|
|
|
class Student : public Person { … }
|
|
|
|
|
like Java, private data and methods are not inherited
|
|
|
|
|
constructors
|
|
|
|
|
base class constructor invoked in the initializer list
|
|
|
|
|
e.g., Student::Student(string name, string school) : Person(name) { … }
|
|
|
|
|
initializer list can include more than just base class constructor (see property example files)
|
|
|
|
|
overriding
|
|
|
|
|
a base class method can be overridden in the derived class by providing a definition with the same name and type
|
|
|
|
|
#include <iostream> using namespace std;
class A { public: void m1() { cout << "a1"; } virtual void m2() { cout << "a2"; } };
class B : public A { void m1() { cout << "b1"; } void m2() { cout << "b2"; } };
int main() { A* x = new B(); x->m1(); x->m2(); }
|
|
|
|
|
B overrides both methods it inherits from A
|
|
|
|
|
dynamic dispatch
|
|
|
|
|
how does C++ decide what version of an overridden method to call?
|
|
|
|
|
through the use of the virtual keyword
|
|
|
|
|
when a method is called at runtime, there are two possibilities
|
|
|
|
|
(1) choose the version of the method according to the type of the pointer
|
|
|
|
|
(2) choose the version of the method according to the actual type of underlying object
|
|
|
|
|
if the base class method was declared virtual, option (2) is used
|
|
|
|
|
otherwise, option (1) is used
|
|
|
|
|
exercise: what does main print out in the above code?
|
|
|
|
|
a1b2
|
|
|
|
|
inheritance considered harmful (rant)
|
|
|
|
|
an object is a combination of data and methods that use that data
|
|
|
|
|
inheritance causes this to be split across multiple files
|
|
|
|
|
to understand the behavior of any derived class, the entire class hierarchy must be inspected
|
|
|
|
|
what do we actually want when we use inheritance?
|
|
|
|
|
code reuse
|
|
|
|
|
polymorphism
|
|
|
|
|
being able to treat a heterogenous set of objects all as the same base class type
|
|
|
|
|
most of the time, we can get these things without using traditional inheritance
|
|
|
|
|
alternatives to inheritance
|
|
|
|
|
code reuse
|
|
|
|
|
composition
|
|
|
|
|
want class B to borrow functionality from class A?
|
|
|
|
|
put an instance of class A inside class B
|
|
|
|
|
polymorphism
|
|
|
|
|
interfaces
|
|
|
|
|
achieve in C++ through pure virtual functions
|
|
|
|
|
int foo(int a, int b) = 0;
|
|
|
|
|
results in an abstract class (cannot have an instance, derived class must implement)
|
|
|
|
|
a lot more inheritance craziness in C++
|
|
|
|
|
private and protected inheritance
|
|
|
|
|
multiple inheritance
|
|
|