More about Inheritance. Static and Dynamic Binding Compiler finds which part of the code should be...

30
More about Inheritance
  • date post

    22-Dec-2015
  • Category

    Documents

  • view

    216
  • download

    0

Transcript of More about Inheritance. Static and Dynamic Binding Compiler finds which part of the code should be...

More about Inheritance

Static and Dynamic Binding

Compiler finds which part of the code should be executed when a function calls.

Interpreting a function invoking is called binding .

This task is simple in C , each name is for one function.

In C++ binding is a complex task because of function overloading.

In some cases binding can be done in compilation time, static binding .

For virtual function we can’t decide which function should be executed.

This task should be done in running time, dynamic binding ( late binding) .

Dynamic binding in C++ associated with methods invoked by pointers and references.

HSBCplus op;HSBC *bp;bp=&op;bp->ViewAcct();

The compiler uses static binding for nonvirtual function.

The compiler uses dynamic binding for virtual function.

Things to Know About Virtual

Beginning a class method declaration with virtual in the base class makes the function for the base class and all classes derived from the base

class virtual.

If a virtual method is invoked by reference or pointer to an object, the program uses the method defined for the object type rather than the method defined for the reference or pointer type. (dynamic binding)

If you’re defining a class that will be used as a base class for inheritance, you should declare as virtual functions the class methods that may have to redefined in the derived classes.

Constructors can’t be virtual. Derived class doesn’t inherit the base class constructors.

Destructors should be virtual unless a class is not a base class.

Example : employee *pe =new singer; …

delete pe; // ~employee() or ~singer() ? If we don’t use virtual, delete invokes the ~employee()

destructor. Frees only memory pointed by employee components of the singer object.

If destructor is virtual first ~singer() is invoked and then ~employee()

Friends can not be virtual functions, because they are not member function.

If we have a chain of derivation, the most resent version of the function is used.

(function hiding )

class Base{ public : virtual void show(int a);….}; class Derived : public Base{ public : virtual void show();};

Derived temp;temp.show(); // validtemp.show(5) // invalid.

• The new definition hides the base class version . Redefining inherited methods is not a variation of overloading.

If we redefine a function in a derived class;

• It doesn’t just override the base class declaration with the same function signature.

• It hides all base-class methods of the same name.

If you redefined an inherited method you need to make sure you match the original prototype.

Exception:

Return type that is a reference or pointer to a base class can be replaced by reference

or pointer to the derived class.

class Base{ public : virtual Base & build(int n);….}; class Derived : public Base{ public : virtual Derived & build(int n);};

We need to redefine all the base class versions in the derived class.

class Base{ public : virtual void show(int a); virtual void show(double x); virtual void show( ); …. }; class Derived : public Base{ public : virtual void show(int a); virtual void show(double x); virtual void show();};

Access Control :protected

• Protected access : Like private access the outside class can have access to them through the public member.

• Member of the derived class can access protected member of the base class directly, but no direct access to the private member.

class HSBC{ protected : double balance; …}; void HSBCplus :: withdraw (double amt) { if( amt < balance) HSBC::Withdraw(); else if (amt <=balance+maxLoan-owesBank){ double advance=amt-balance; owesBank+=advance*(1.0+rate); cout<< “Bank Advance: $ ” <<advance<<endl; cout<<“Finace Charge: $ “<<advance*rate<<endl; Deposit(advance); HSBC::Withdraw(amt); } else cout<<“ Credit Limit exceeded”;}

Abstract Base Classes

Consider ellipse and circle in a graphic program: Suppose we have the following fields for ellipse class : class Ellipse{ private : double x; double y; double a, b; // short axis and long axis double angle; // orientation angle in degree … public : virtual void Move(int x, int y) { x=nx; y=ny;} virtual double Area() { return 3.1459*a*b;}

virtual void Rotate( double nang) {angle+=nang;}

virtual void Scale( double sa, double sb) {a*=sa; b*=sb; }

…..

};

Since circle is an ellipse we can derived circle class from base class.

But we should be careful since a=b, and rotate doesn’t make sense for circle. Angle is not needed for circle.

Better to write a separate class for circle :

class Circle{ private : double x; double y; double r; // radius… public : void Move(int x, int y) { x=nx; y=ny;} double Area() { return 3.1459*r*r;} void Scale( double sr) {r*=sr; }…};

Another Solution

Abstract the common features from Ellipse and Circle class and place them in an ABC.

Derived both ellipse and circle classes from the ABC.

class BaseEllipse { private : double x,y; … public : BaseEllipse ( double x0=0; double y0=0) : x(x0) ,

y(y0){ } virtual ~BaseEllipse() { } void Move ( int nx, int ny) {x=nx; y=ny;} virtual double Area() =0 ; // make it pure virtual ….};

=0 indicates that the class is an ABC and class doesn’t have to define a function.

But we still can define the function in cpp file

An ABC describes an interface that uses at least one pure virtual function.

Example :

#ifndef ACCTABC_H_

#define ACCTABC_H_

class AcctABC {

private :

enum {MAX =35};

char fullName[MAX];

long acctNum;

double balance;

protected :

const char * FullName() { return fullName};

long AcctNum() { return acctNum;}

public :

AcctABC( const char * s="Nullbody", long an=-1, double bal =0.0); void Deposit(double amt); virtual void Withdraw(double amt) =0; double Balance () { return balance;} virtual void ViewAcct() =0; virtual ~ AcctABC() { }

};

class HSBC: public AcctABC{ public : HSBC(const char * s="Nullbody", long an=-1, double bal

=0.0) : AcctABC(s,an,bal) { } virtual void Withdraw(double amt) ; virtual void ViewAcct(); virtual ~ HSBC() { }};

class HSBCPlus: public AcctABC{ private : double maxLoan; double rate; double owesBank; public : HSBCPlus(const char * s="Nullbody", long an=-1, double bal =0.0,

double ml=500, double r=0.10);

HSBCPlus(const HSBC & hs, double ml=500, double r=0.10);

virtual void Withdraw(double amt) ; virtual void ViewAcct(); void ResetMax(double m) { maxLoan =m;} void ResetRate(double r) { rate =r; } void ResetOwes() { owesBank =0; }};#endif

#include<iostream.h>#include<cstring>#include "acctabc.h"

AcctABC :: AcctABC (const char *s, long an, double bal)

{ strncpy(fullName,s,MAX-1); fullName[MAX-1]='\0'; acctNum=an; balance=bal;}

void AcctABC::Deposit(double amt){ if( amt<0) cout<<"No negative deposit";else balance+=amt;}

void AcctABC::Withdraw(double amt){ balance-=amt;}

void HSBC::Withdraw(double amt){ if( amt < 0) cout<< "No negative withdraw"; else if( amt <= Balance()) AcctABC:: Withdraw(amt); else cout<<"Not enough balance"; }

void HSBC::ViewAcct(){ cout<<"client: " <<FullName()<<endl; cout<<"Account Num:" <<AcctNum()<<endl; cout<<"Balance: $"<<Balance()<<endl;}

HSBCPlus::HSBCPlus(const char *s,long an, double bal, double ml, double r ) : AcctABC(s,an,bal)

// member initialize list{ maxLoan=ml; owesBank=0.0; rate=r; }

HSBCPlus::HSBCPlus(const HSBC &hs , double ml, double r ) : AcctABC(hs)

{ maxLoan=ml; owesBank=0.0; rate=r; }

void HSBCPlus:: ViewAcct(){ cout<<"HSBCPlus client: "

<<FullName()<<endl; cout<<"Acct Number" <<AcctNum()<<endl; cout<<"Balance: $"<<Balance()<<endl; cout<<"maxloan: $" <<maxLoan<<endl; cout<<"OwesBank: $" <<owesBank<<endl; cout<<"Loan Rate: $"<<100*rate<<"%\n";}

void HSBCPlus::Withdraw(double amt){ double bal=Balance();

if( amt <= bal) AcctABC::Withdraw(amt);

else if (amt <=bal+maxLoan-owesBank){ double advance=amt-bal; owesBank+=advance*(1.0+rate); cout<< "Bank Advance: $ "<<advance<<endl; cout<<"Finace Charge: $ "<<advance*rate<<endl; Deposit(advance); AcctABC::Withdraw(amt); } else cout<<"Credit Limit exceeded";}