Search

Sponsored Links

Meta

Categories

Archives

Recent Posts

RSS Feeds

07
Dec

C++ Advanced Tutorial - Lesson 2

Related Blog Items

Please refer Lesson 1..

2. MULTIPLE INHERITANCE
2.1 Multiple Inheritance and Interface
2.2 Virtual Inheritance
2.3 Method Name Clash and Ambiguity in Multiple Inheritance

2. MULTIPLE INHERITANCE

2.1 Multiple Inheritance and Interface

It is commonly believed that multiple inheritance tends to mass things up. That’s why Java language which is a simplified version of C++ forbids multiple inheritance. However, multiple inheritance from interfaces can be very helpful. That’s why Java specifically introduced the concept of interface. In C++ interface can be represented by an abstract class with all methods being pure virtual.

An interface groups a number of methods which are logically closely related. It represents one of possibly many aspects of a data type. For example, a Human class may depict many aspects of a person - a person has its psychological aspect, physical aspect, experience aspect, technical skills aspect, hobbies aspect, family aspect, etc. If all methods are grouped in one class, firstable there may be a hundred classes and it may appear to be quite dounting, secondly if another program only wants to deal with one aspect of Human class say the physical aspect such as weight, height, blood pressure, etc., it will have to store a reference to the whole class, and will be able to know about all other unneeded aspects of the class such as the person’s technical skills. This is typically not desireable. We want objects to know as little as possible about each other, so that they are loosely coupled.

If we have a group of interfaces each representing one aspect of Human, and let Human inherit from and implement all these interfaces, such as IPsychological, IPhysical, ITechnical, IFamily, then e.g. interface IPhysical will only include methods such as GetHeight, GetWeight, GetBloodPressure, etc. It is logically more simple, and more importantly, if an other program only wants to deal with the physical aspect of Human, it can store a IPhysical reference, then it does not know any other aspects of the Human class. Information hiding is much better achieved.

This mechanism is enforced in COM programming. Clients can never get a reference to the whole class. They only get references to interfaces.

2.2 Virtual Inheritance

When one class inherits from more than one classes, that is called multiple inheritance. Among multiple inheritance, there is a special case called diamond inheritance. One example is: class ostream and istream both inherits from class ios, and class iostream inherits from both istream and ostream.
In polymorphism, when we let a base-class pointer point to a derived-class object, that pointer actually points to the base-class object within the derived-class object. In diamond inheritance, however, because the derived class contains two duplicated base-class objects, compiler doesn’t know which part the pointer should point to. Therefore it will prompt an error message.
Example:

class Base {};
class Derived1 : public Base {};
class Derived2 : public Base {};
class Multi : public Derived1, public Derived2 {};
The following statement is illegal:
 
Base * ptr = new Multi;
But the following statements are legal:
 
Derived1 * ptr1 = new Multi;
Derived2 * ptr2 = new Multi;
because the compiler can locate the Derived1 or Derived2 part of object in Multi object.
To solve this problem, use virtual inheritance, which only allows one sub-object:
 
class Base {};
class Derived1 : virtual public Base {};
class Derived2 : virtual public Base {};
class Multi : public Derived1, public Derived2 {};
 
int main()
{   Base * ptr = new Multi; }

2.3 Method Name Clash and Ambiguity in Multiple Inheritance

Suppose class Derived inherits from two base classes Base1 and Base2, each has an implemented virtual method Hi with the same signature. If class Derived provides its own implementation of Hi, then the function pointers of method Hi in the two vtables of Base1 and Base2 will both point to Derived’s implementation. Therefore the two different implementations provided by Base1 and Base2 are supressed.
If Derived does not provide its own implementation, the two implementations in the base classes are retained. However, when you call this method through a reference of Derived, no one knows which implementation you want to call. Compiler will complain over this call. You can only call through a base-class vPtr, so that the program knows which implementation you are calling:

#include "stdafx.h"
 
struct Base1 
{
  virtual void Hi() 
  {    printf("Hi from Base1!\n");  }
};
 
struct Base2 
{
  virtual void Hi() 
  {    printf("Hi from Base2!\n");  }
};
 
struct Derived : public Base1, Base2 {};
 
int main(int argc, char* argv[])
{
  Derived * pDerived = new Derived;
  pDerived->Hi();            // Ambiguity! 
  ((Base1 *)pDerived)->Hi(); // Base1::Hi will be called
  ((Base2 *)pDerived)->Hi(); // Base2::Hi will be called
  return 0;
}

Popularity: 21%

You need to log on to convert this article into PDF


Related Blog Items

No Comments

No comments yet.

Leave a comment

*
To prove you're a person (not a spam script), type the security word shown in the picture.
Anti-spam image