|< C++ Inheritance 4 | Main | C++ Multi Inheritance 1 >| Site Index | Download |


 

 

 

 

MODULE 15a_1

FINAL  PART  ON  C++  INHERITANCE  5

 

 

 

 

 

 

 

 

My Training Period: xx hours

 

This is a continuation from previous Module and a final part. The source code for this tutorial is available in C++ Inheritance source codes.

 

15.12    Friend Functions And Class

  • A function/method outside of a class can be defined to be a friend function by the class which gives the friend function free access to the private or protected members of the class.

  • This is done by preceding the function prototype in the class declaration with keyword friend.  For example:

  private:

      friend void set(int new_length, int new_width);

      // friend method

      friend int get_area(void) {return (length * width);}

      // friend method

  • So, set() and get_area() functions still can be used to access members of the class.

  • This in effect, opens a small hole in the protective shield of the class, so it should be used very carefully.

  • A single isolated function can be declared as a friend, as well as members of other classes, and even entire classes can be given friend status if needed in a program.  Neither a constructor nor a destructor can be a friend function.

  • When friendship is granted, so for class Y to be a friend of class X, class X must declare that class Y is its friend.

  • Class friendship is not transitive: X friend of Y and Y friend of Z does not imply X friend of Z, also it is not inherited.

  • By using friend, you can see that it has weakened the data hiding.  You should implement this only when there is no way to solve your programming problem.

  • A simple program example:

// using friend function...

#include <iostream>

using namespace std;

 

class SampleFriend

{

   // private member variable

   int i;

   friend  int  friend_funct(SampleFriend *, int);

   // friend_funct is not private,

   // even though it's declared in the private section

   public:

       // constructor

       SampleFriend(void) { i = 0;};

       int member_funct(int);

};

 

// implementation part, both functions access private int i

int  friend_funct(SampleFriend *xptr, int a)

{

  return xptr->i = a;

}

 

int  SampleFriend::member_funct(int a)

{

    return i = a;

}

 

main()

{

    SampleFriend    xobj;

    // note the difference in function calls

 

    cout<<"\nfriend_funct(&xobj, 10) is "<<friend_funct(&xobj, 10)<<"\n\n";

    cout<<"xobj.member_funct(10) is "<<xobj.member_funct(10)<<endl;

}

 

Output:

 

C++ object class inheritance friend function illustration example

class One

{

   friend Two;

   int i;

   void member_funcOne();

};

 

class Two;

{                   

   void friend_One1(One&);

   void friend_One2(One*);

  ...

  ...

};

 

 

 

 

 

 

More Working Program Examples and Experiments

 

 

 

 

 

// inheritance again...

// notice the sequence of the constructor

// and destructor, and private, public, protected usage...

#include <iostream>

using namespace std;

 

class Base

{

     // available for this class member functions ONLY...

     private:

         int BaseVar;

         int NewX;

         int ExtraBaseVar;

        

      // available to this and derived classes...

      protected:

          int BaseVarOne;

    

      // available to the derived and outside classes...

      public:

          Base();

          Base(int NewX);

          ~Base();

      public:

          int SetBaseData();

          int ShowBaseData(){return BaseVar;}

          int SimilarNameFunct();

};

 

class DerivedOne:public Base

{

     // available to this class member functions ONLY...

     private:

          int DerivedOneVar;

          int ExtraDerivedVar;

         

     // available to the derived and outside classes...

     public:

          DerivedOne();

          ~DerivedOne();

         

     // available to the derived and outside classes...

     public:

          void SetDerivedOneData();

          int ShowDerivedOneData()

      {

           // BaseVarOne is base class protected member

           // variable, available to this derived class...

           return (DerivedOneVar + BaseVarOne);

      }

      int SimilarNameFunct();

};

 

// base class constructor...

Base::Base()

{

  BaseVar = 100;

  // constructor counter...

  static int p;

  cout<<"Invoking base class constructor #"<<p<<endl;

  p++;

}

 

// another base class constructor...

Base::Base(int)

{

  // constructor counter...

  static int t;

  cout<<"Invoking 2nd base class constructor #"<<t<<endl;

  t++;

  BaseVar = NewX;

}

 

// base class member function...

int Base::SetBaseData()

{ return NewX = 230;}

 

int Base::SimilarNameFunct()

{return ExtraBaseVar = 170;}

 

// base class destructor...

Base::~Base()

{

  // destructor counter...

  static int q;

  cout<<"Invoking base class destructor #"<<q<<endl;

  q++;

}

 

// derived class constructor...

DerivedOne::DerivedOne()

{

  DerivedOneVar = 200;

  // this member variable is inherited from protected base class

  BaseVarOne = 250;

 

  // constructor counter...

  static int r;

  cout<<"Invoking derived class constructor #"<<r<<endl;

  r++;

}

 

// derived class destructor...

DerivedOne::~DerivedOne()

{

  // destructor counter...

  static int s;

  cout<<"Invoking derived class destructor #"<<s<<endl;

  s++;

}

 

void DerivedOne::SetDerivedOneData()

{}

 

// same member function name as base class

// it is valid since they are from different class

int DerivedOne::SimilarNameFunct()

{return ExtraDerivedVar = 260;}

 

void main()

{

      // instantiate objects with class types...

      Base ObjOne, ObjFour;

      DerivedOne ObjTwo, ObjFive;

 

      Base ObjThree;

 

      cout<<"Base class data = "<<ObjOne.ShowBaseData()<<endl;

      cout<<"SimilarNameFunct() of base class = "<<ObjFour.SimilarNameFunct()<<endl;

      cout<<"DerivedOne class data = "<<ObjTwo.ShowDerivedOneData()<<endl;

      cout<<"SimilarNameFunct() of derived class = "<<ObjFive.SimilarNameFunct()<<endl;

      cout<<"Another base class data = "<<ObjThree.SetBaseData()<<endl;

 

}

 

Output:

 

C++ class inheritance and class hierarchy program output example

 

  • If you cannot see the full output in Borland, you have to use its debugger (Turbo Debugger).  From the output snapshot screen you can see that the destructors were invoked in the reverse order of the constructors.

  • From the output screen also we can conclude that the process involved for objects are:

  1. Allocating storage for the objects instantiation.

  2. Manipulate the objects such as storing, assigning, displaying the objects data etc.

  3. Finally destroy all the allocation and objects.

  • Very nice huh!!!

  • The following is a program example compiled using VC++/VC++ .Net.

 

// program inherit3.cpp

#include  <iostream>

using namespace std;

 

// base and derived class declaration part

class vehicle

{

  protected:

      int wheels;

      double weight;

    

  public:

       void   initialize(int input_wheels, double input_weight);

       int    get_wheels(void)      {return  wheels;}

       double get_weight(void)      {return  weight;}

       double wheel_load(void)      {return  (weight/wheels);}

};

 

// public keyword changed to private - private inheritance

class car : private vehicle

{

   int   passenger_load;

 

   public:

       void initialize(int input_wheels, double input_weight, int people = 4);

       int passengers(void)        {return  passenger_load;}

};

 

// public keyword change to private - private inheritance

class truck : private vehicle

{

   int  passenger_load;

   double payload;

   public:

       void init_truck(int how_many = 4, double max_load = 24000.0);

       double efficiency(void);

       int passengers(void)        {return  passenger_load;}

};

 

// main program

int main()

{

   vehicle unicycle;

   unicycle.initialize(1, 12.5);

 

   cout<<"Using base class, vehicle with public methods\n";

   cout<<"---------------------------------------------\n";

   cout<<"The unicycle has "<<unicycle.get_wheels()<<" wheel.\n";

   cout<<"The unicycle's wheel load is "<<unicycle.wheel_load()<<" kg on the single

                                                            tire.\n";

   cout<<"The unicycle weighs "<<unicycle.get_weight()<<" kg.\n\n";

 

   car sedan_car;

   sedan_car.initialize(4, 3500.0, 5);

 

   cout<<"\nThese two are public-->sedan_car.initialize(4,3500.0,5)\n";

   cout<<"           and  sedan_car.passengers()\n";

   cout<<"-------------------------------------------------------\n";

   cout<<"The sedan car carries "<<sedan_car.passengers()<<" passengers.\n";

   // methods get_weight() and wheel_load() not available

   // because we use private inheritance

   // cout<<"The sedan car weighs "<<sedan_car.get_weight()<<" kg.\n";

   // cout<<"The sedan car's wheel loading is "<<sedan_car.wheel_load()<<" kg per

   //                                             tire.\n\n";

 

   truck trailer;

  // trailer.initialize(18, 12500.0);

  // this method is private now

  trailer.init_truck(1, 33675.0);

 

  cout<<"\nThese are public-->trailer.init_truck(1, 33675.0),\n";

  cout<<" trailer.efficiency() and trailer.passengers()\n";

  cout<<"--------------------------------------------------\n";

  cout<<"\nOthers are private...\n";

  // methods get_weight() and efficiency() not available

  // because we use private inheritance

  // cout<<"The trailer weighs "<<trailer.get_weight()<<" kg.\n";

  // cout<<"The trailer's efficiency is "<<100.0 * trailer.efficiency()<<" %.\n";

  return 0;

}

 

// class implementation part

// initialize to any data desired, method own by base class

void vehicle::initialize(int input_wheels, double input_weight)

{

   wheels = input_wheels;

   weight = input_weight;

}

 

// method own by derived class

void car::initialize(int input_wheels, double input_weight, int people)

// wheels and weight still available because of the protected keyword

   passenger_load = people;

   wheels = input_wheels;

   weight = input_weight;

}

 

void truck::init_truck(int how_many, double max_load)

{

   passenger_load = how_many;

   payload = max_load;

}

 

double truck::efficiency(void)

{

    return (payload / (payload + weight));

}

 

Output:

 

 

 

 

 

 

 

 

 

 

 

C++ class inheritance compilation using Microsoft Visual C++ .Net

 

///// -herit.cpp- ///////////////////////

// notice the sequence of the constructor

// and destructor, and the use of private,

// public and protected. The inheritance...

//////-FEDORA 3, g++ x.x.x- /////////////

#include <iostream>

using namespace std;

 

class Base

{

      // available for this class member functions ONLY...

      private:   // the keyword is optional for private

          int BaseVar;

          int NewX;

          int ExtraBaseVar;

        

      // available to this and derived classes...

      protected:

          int BaseVarOne;

 

      // available to the derived and outside classes...

      public:

          Base();

          Base(int NewX);

          ~Base();

      public:

          int SetBaseData();

          int ShowBaseData(){return BaseVar;}

          int SimilarNameFunct();

};

 

class DerivedOne:public Base

{

      // available to this class member functions ONLY...

      private:

          int DerivedOneVar;

          int ExtraDerivedVar;

     

      // available to the derived and outside classes...

      public:

          DerivedOne();

          ~DerivedOne();

     

      // available to the derived and outside classes...

      public:

          void SetDerivedOneData();

          int ShowDerivedOneData()

      {

        // BaseVarOne is base class protected member

        // variable, available to this derived class...

        return (DerivedOneVar + BaseVarOne);

      }

      int    SimilarNameFunct();

};

 

// base class constructor...

Base::Base()

{

        BaseVar = 100;

        // constructor counter...

        static int p;

        cout<<"Invoking base class constructor #"<<p<<endl;

        p++;

}

 

// another base class constructor...

Base::Base(int)

{

        // constructor counter...

        static int t;

        cout<<"Invoking 2nd base class constructor #"<<t<<endl;

        t++;

        BaseVar = NewX;

}

 

// base class member function...

int Base::SetBaseData()

{return NewX = 230;}

 

int Base::SimilarNameFunct()

{return ExtraBaseVar = 170;}

 

// base class destructor...

Base::~Base()

{

        // destructor counter...

        static int q;

        cout<<"Invoking base class destructor #"<<q<<endl;

        q++;

}

 

// derived class constructor...

DerivedOne::DerivedOne()

{

        DerivedOneVar = 200;

        // this member variable is inherited from protected base class

        BaseVarOne = 250;

 

        // constructor counter...

        static int r;

        cout<<"Invoking derived class constructor #"<<r<<endl;

        r++;

}

 

// derived class destructor...

DerivedOne::~DerivedOne()

{

        // destructor counter...

        static int s;

        cout<<"Invoking derived class destructor #"<<s<<endl;

        s++;

}

 

void DerivedOne::SetDerivedOneData()

{ }

 

// same member function name as base class

// it is valid since they are from different class

int DerivedOne::SimilarNameFunct()

{return ExtraDerivedVar = 260;}

 

int main()

{

      // instantiate objects with class types...

      Base ObjOne, ObjFour;

      DerivedOne ObjTwo, ObjFive;

 

      Base ObjThree;

 

      cout<<"Base class data = "<<ObjOne.ShowBaseData()<<endl;

      cout<<"SimilarNameFunct() of base class = "<<ObjFour.SimilarNameFunct()<<endl;

      cout<<"DerivedOne class data = "<<ObjTwo.ShowDerivedOneData()<<endl;

      cout<<"SimilarNameFunct() of derived class = "<<ObjFive.SimilarNameFunct()<<endl;

      cout<<"Another base class data = "<<ObjThree.SetBaseData()<<endl;

      return 0;

}

 

[bodo@bakawali ~]$ g++ herit.cpp -o herit

[bodo@bakawali ~]$ ./herit

 

Invoking base class constructor #0

Invoking base class constructor #1

Invoking base class constructor #2

Invoking derived class constructor #0

Invoking base class constructor #3

Invoking derived class constructor #1

Invoking base class constructor #4

Base class data = 100

SimilarNameFunct() of base class = 170

DerivedOne class data = 450

SimilarNameFunct() of derived class = 260

Another base class data = 230

Invoking base class destructor #0

Invoking derived class destructor #0

Invoking base class destructor #1

Invoking derived class destructor #1

Invoking base class destructor #2

Invoking base class destructor #3

Invoking base class destructor #4

 

tenouk C++ inheritance object oriented tutorial

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Further C++ Inheritance reading:

 

  1. The C++ .NET programming tutorials.
  2. This is a continuation from previous Module. The source code for this tutorial is available in C++ Inheritance source codes.
  3. Check the best selling C / C++ and object oriented books at Amazon.com.
  4. See MFC library class hierarchy chart here.
  5. Find a lot of information about C++ history and evolution at Bjarne Stroustrup site.

 

 

 

 

 

 

 

|< C++ Inheritance 4 | Main | C++ Multi Inheritance 1 >| Site Index | Download |


C++ Inheritance Features:  Part 1 | Part 2 | Part 3 | Part 4