150 likes | 296 Views
Inheritance in C++. Content adapted from a lecture by Dr Soo Yuen Jien. Bank Account. Saving Account. class BankAccount { private : int _ n um ; int _bal; public : BankAccount ( int num , int bal ){ _ num = num ; _ bal = bal ; } //withdraw method
E N D
Inheritancein C++ • Content adapted from a lecture by DrSoo Yuen Jien
Bank Account Saving Account • classBankAccount { • private: • int_num; • int _bal; • public: • BankAccount(intnum, intbal){ • _num = num; • _bal = bal; • } • //withdraw method • //deposit method • //print method • }; • classSavingAccount { • private: • int_num; • int _bal;int_rate; • public: • SavingAccount(intnum, intbal, int rate){ • _num = num; • _bal = bal; • _rate = rate; • } • //withdraw method • //deposit method • //print method • //pay_interest method • }; Now, we want to implement a SavingAccount that also has the same attributes and methods, but in addition, has an extra attribute to store the interest rate and an extra method to pay interest. Let’s say we wrote a BankAccount class to represent a bank account. It has some private attributes, a constructor, and some public methods.
Bank Account Saving Account • classBankAccount { • private: • int_num; • int _bal; • public: • BankAccount(intnum, intbal){ • _num = num; • _bal = bal; • } • //withdraw method • //deposit method • //print method • }; • classBankAccount { • private: • int_num; • int _bal; • public: • BankAccount(intnum, intbal){ • _num = num; • _bal = bal; • } • //withdraw method • //deposit method • //print method • }; • classSavingAccount { • private: • int_num; • int _bal;int_rate; • public: • SavingAccount(intnum, intbal, int rate){ • _num = num; • _bal = bal; • _rate = rate; • } • //withdraw method • //deposit method • //print method • //pay_interest method • }; • classBankAccount { • private: • int_num; • int _bal; • public: • BankAccount(intnum, intbal){ • _num = num; • _bal = bal; • } • //withdraw method • //deposit method • //print method • }; One solution is to write the SavingAccount class by copy pasting the BankAccount code,
Bank Account Saving Account • classBankAccount { • private: • int_num; • int _bal; • public: • BankAccount(intnum, intbal){ • _num = num; • _bal = bal; • } • //withdraw method • //deposit method • //print method • }; • classSavingAccount { • private: • int_num; • int _bal;int_rate; • public: • SavingAccount(intnum, intbal, intrate){ • _num = num; • _bal = bal; • _rate = rate; • } • //withdraw method • //deposit method • //print method • //pay_interest method • }; That however results in a high level of code duplication. Duplicated code is hard to maintain because any change to one copy needs to be replicated in all copies of the code. and modifying as necessary.
Bank Account Saving Account • classBankAccount { • private: • int_num; • int _bal; • public: • BankAccount(intnum, intbal){ • _num = num; • _bal = bal; • } • //withdraw method • //deposit method • //print method • }; • classSavingAccount { • private: • int_num; • int _bal;int_rate; • public: • SavingAccount(intnum, intbal, int rate){ • _num = num; • _bal = bal; • _rate = rate; • } • //withdraw method • //deposit method • //print method • //pay_interest method • };
Bank Account Saving Account • classBankAccount { • private: • int_num; • int _bal; • public: • BankAccount(intnum, intbal){ • _num = num; • _bal = bal; • } • //withdraw method • //deposit method • //print method • }; • classSavingAccount: publicBankAccount{ • private: • int_rate; • public: • SavingAccount(intnum, intbal, int rate) • :BankAccount(num, bal){ • _rate = rate; • } • //pay_interest method • }; protected: BankAccount SavingAccount inherited inherited (parent class, super class) (child class, sub-class) That way, all attributes and methods of the BankAccount class are inherited by the SavingAccount class, without needing to define them again. But note that we need to change the visibility of these attributes for them to be visible to the SavingAccount class. Private members are not visible to sub classes. Because the sub-class is defined based on the parent class, the constructor of the sub-class needs to call the constructor of the super class. This is the syntax for that. The sub class needs to contain extra attributes and methods only. There is no need to repeat the inherited attributes and methods. Instead, we can use inheritance to define the SavingAccount based on the existing BankAccount class. This is the syntax for declaring SavingAccount as a sub-class of BankAccount class.
Bank Account Saving Account • classBankAccount { • private: • int_num; • int _bal; • public: • BankAccount(intnum, intbal){ • _num = num; • _bal = bal; • } • //withdraw method • //deposit method • //print method • }; • classSavingAccount: publicBankAccount{ • private: • int_rate; • public: • SavingAccount(intnum, intbal, int rate) • :BankAccount(num, bal){ • _rate = rate; • } • //pay_interest method • }; protected: BankAccount SavingAccount inherited inherited (parent class, super class) (child class, sub-class)
classBankAccount { • protected: • int_num; • int _bal; • public: • BankAccount(intnum, intbal){ • _num = num; • _bal = bal; • } • //withdraw method • //deposit method • //print method • }; • classSavingAccount: publicBankAccount{ • private: • int_rate; • public: • SavingAccount(intnum, intbal, int rate) • :BankAccount(num, bal){ • _rate = rate; • } • //pay_interest method • }; intmain( ){ SavingAccountsa( 8888, 999, 2 ); sa.deposit(1000); sa.payInterest(); } Inherited method from super class BankAccount New method in SavingAccount class Now, let’s see how we use the inherited classes. First, we create a SavingAccount object. Then, we can call methods it inherited from the super class, and methods defined in the sub class too.
classBankAccount { • protected: • int_num; • int _bal; • public: • BankAccount(intnum, intbal){ • _num = num; • _bal = bal; • } • //withdraw method • //deposit method • //print method • }; • classSavingAccount: publicBankAccount{ • private: • int_rate; • public: • SavingAccount(intnum, intbal, int rate) • :BankAccount(num, bal){ • _rate = rate; • } • //pay_interest method • }; voidtransfer(BankAccount& fromAcct, BankAccount& toAcct, intamt){ fromAcct.withdraw( amt ); toAcct.deposit( amt ); } intmain( ) { BankAccountba( 1, 234 ); SavingAccountsa( 2, 2000, 3 ); transfer( ba, sa, 234 ); } Super class expected Sub-class given It still works because of the substitutability principle: If the code expects an object of the super class, it will also work with an object of the sub class. Let’s say we created this method to transfer money from one BankAccount to another BankAccount. Here, we are passing a SavingAccount object to that method although it expects a BankAccount object.
classBankAccount { • protected: • int_num; • int _bal; • public: • BankAccount(intnum, intbal){ • _num = num; • _bal = bal; • } • //withdraw method • //deposit method • voidprint() { • cout << "Number:" << _num ; • cout << "\nBalance:", << _bal ; • } • }; • classSavingAccount: publicBankAccount{ • private: • int_rate; • public: • SavingAccount(intnum, intbal, int rate) • :BankAccount(num, bal){ • _rate = rate; • } • //pay_interest method • voidprint() { • cout << "Number:" << _num ; • cout << "\nBalance:", << _bal; • cout << "\nRate:" << _rate ; • } • }; e.g. Number:1234 Balance:100 e.g. Number:1234 Balance:100 Rate:2 overrides Suppose this is the print method in the BankAccount class. Currently, it is inherited by the SavingAccount class too. What if we want SavingAccount objects to print in a different way? In that case, we can override the print method in the SavingAccount class by simply re-implementing it.
classBankAccount { • protected: • int_num; • int _bal; • public: • BankAccount(intnum, intbal){ • _num = num; • _bal = bal; • } • //withdraw method • //deposit method • voidprint() { • cout << "Number:" << _num ; • cout << "\nBalance:", << _bal ; • } • }; • classSavingAccount: publicBankAccount{ • private: • int_rate; • public: • SavingAccount(intnum, intbal, int rate) • :BankAccount(num, bal){ • _rate = rate; • } • //pay_interest method • voidprint() { • cout << "Number:" << _num ; • cout << "\nBalance:", << _bal; • cout << "\nRate:" << _rate ; • } • }; BankAccount::print(); Notice how these lines are duplicated. To avoid this duplication, we can simply call the method of the super class from the sub class.
classBankAccount { • protected: • int_num; • int _bal; • public: • BankAccount(intnum, intbal){ • _num = num; • _bal = bal; • } • //withdraw method • //deposit method • voidprint() { • cout << "Number:" << _num ; • cout << "\nBalance:", << _bal ; • } • }; • classSavingAccount: publicBankAccount{ • private: • int_rate; • public: • SavingAccount(intnum, intbal, int rate) • :BankAccount(num, bal){ • _rate = rate; • } • //pay_interest method • voidprint() { • cout << "Number:" << _num ; • cout << "\nBalance:", << _bal; • cout << "\nRate:" << _rate ; • } • }; BankAccount SavingAccount BankAccount::print(); (parent class, super class) (child class, sub-class) Let’s summarize. When a class inherits from another class, it inherits attributes, and methods. The constructor of the child class should call one of the constructors of the super class. The sub class can override methods from the super class. It can call methods from the super class too.
Inheritancein C++ • Content adapted from a lecture by DrSoo Yuen Jien • Created using http://PowerPointLabs.info