From C++ Multiple Inheritance to Interfaces.  
Author Message
ARehman





PostPosted: Visual C++ Language, From C++ Multiple Inheritance to Interfaces. Top

Hi,

    I want to understand what was/were the problem(s) with c++ mutliple inheritance model except Diamond Problem . If we can solve the diamond problem with Scope Resolution operator and we can achieve inheritance and polymorphism, then why we need to introduce a new concept of Interface.

I'm not against the interface concept, it is just that I truly want to understand

  1. Interface edge over c++ multiple inheritance model.
  2. what was/were problem(s) with this model.
  3. what can't be achieved by c++ multiple inheritance.

Thanks.



Visual C++3  
 
 
NewWorldMan





PostPosted: Visual C++ Language, From C++ Multiple Inheritance to Interfaces. Top

My guess is that single inheritance plus multiple interfaces was chosen for:

1. Simplicity.
2. To facilitate language interoperability - most OO languages only support single inheritance.

If you're really missing MI on .NET though, then Eiffel for .NET currently supports it. (There's an MSDN article describing it.) Not sure whether any others do.


 
 
TaylorMichaelL





PostPosted: Visual C++ Language, From C++ Multiple Inheritance to Interfaces. Top

1) Multiple inheritance is not replaced by interfaces. An interface is nothing more than an abstract base class where all members are abstract. C++ supports interfaces directly. Multiple inheritance is used in C++ to combine the base implementation of multiple classes into one. Interfaces don't provide any implementation and therefore should not be compared to multiple inheritance.

The best way to understand the difference between an interface and a base class is that an interface defines the contract that an object will implement but does not provide any details about how it will be done. A base class provides the contract and generally some base implementation. An abstract base class where none of the members are implemented is equivalent to an interface.

2) Now in .NET you can have only single inheritance but multiple interface implementations. Why The problem with multiple inheritance is what happens to the base class members (fields specifically) when they are referenced in a derived class. Looking at the defacto inheritance model used by most developers here is a basic class hierarchy.

class BaseClass
{
public:
void PrintName ( )
{ printf("%s", m_strName.c_str()); }

protected:
string m_strName;
};

class Derived1 : public BaseClass
{
public:
Derived1 ( )
{ m_strName = "Derived1"; }

void PrintName1 ( )
{ PrintName(); }
};

class Derived2 : public BaseClass
{
public:
Derived2 ( )
{ m_strName = "Derived2"; }

void PrintName2 ( )
{ PrintName(); }
};

class MultiDerived : public Derived1, public Derived2
{
};

int _tmain(int argc, _TCHAR* argv[])
{
MultiDerived cls;
cls.PrintName();
return 0;
}


What name will be printed The answer is...it depends. Because we have two base classes there will be two copies of BaseClass inside each instance of MultiDerived (one for each base class). When we work through the members of Derived1 we will be working with one copy of the base class. When we work through the members of Derived2 we will be working with another, completely separate, copy of the base class. In fact since the compiler can't tell which version you wanted it'll fail to compile.

Changing the method call to PrintName1 will cause Derived1 to be printed but calling PrintName2 would cause Derived2 to be printed. Suddenly the implementation detail of who implemented what method becomes visible to your callers. Not a good thing. You can switch to virtual base classes to resolve some of this confusion. Nevertheless this type of issue can be difficult to debug if you have a deep hierarchy and you happen to be looking in the wrong version of the class.

A counterargument could be that each base class should implement independent functionality and therefore shouldn't share any data but this is rarely the case. MFC classes always derive from CObject. .NET types always derive from Object. If you want independent behavior then aggregation is the better approach.

3) Don't understand this question. It seems like the better question would be what can I no longer achieve in .NET that I could using multiple inheritance The answer here is that you lose the ability to get default implementations of basic functionality contained in multiple classes. However you'll quickly learn that you can achieve the same effect by using aggregation to nest class (what would have been the base classes in C++) instances inside another class and use interfaces to expose the contract that is implemented.

The general practice in .NET is to define an interface to represent the contract for some feature. Then create an abstract base class that provides a default implementation of the interface (some members can remain unimplemented). This allows clients to use the base class whenever they can yet still gives them the freedom of just implementing the interface in cases where they already have a base class or would prefer to defined their own implementation. The collection subsystem along with many other areas of .NET follow this paradigm. Finally note that in public code interfaces are almost always used in lieu of abstract base classes when passing them as parameters or returning them from methods or properties. This gives us the ultimate flexibility without worrying about/limiting the underlying implementation details.

Michael Taylor - 1/19/07
http://p3net.mvps.org


 
 
ARehman





PostPosted: Visual C++ Language, From C++ Multiple Inheritance to Interfaces. Top

 Hi Michael,

Thanks for your detailed reply. I really appriciate that. The topic is really interesting and a lot of people like me  need to understand this. Thank you for your time.

  1. "Multiple inheritance is used in C++ to combine the base implementation of multiple classes into one." I got the idea. Althought it's quite silly, but , let us assume for the time being there are classes such that ClassAnimal...ClassCustomer.....ClassSchool...and a class ClassInheritAnimalSchoolCustomer We see here that ClassInheritAnimalSchoolCustomer doesn't form "is a" relationship here by inheriting either of the others two at same time. So doesn't "combine the base implementation into one..." violates the rule So, I mean here that some time one can come across where he will be violating the rule. 
  2. "Interfaces don't provide any implementation and therefore should not be compared to multiple inheritance". You can say that this is a difference, but we do know that people talk that interfaces provide multiple inheritance in java, c#. So, in this context we should be comparing them
  3. "However you'll quickly learn that you can achieve the same effect by using aggregation to nest class (what would have been the base classes in C++) instances inside another class and use interfaces to expose the contract that is implemented." I would like you to give a short example to elaborate this.

Again thanks for you time.

 


 
 
TaylorMichaelL





PostPosted: Visual C++ Language, From C++ Multiple Inheritance to Interfaces. Top

1) In your example I would say that you should not be using inheritance. Inheritance is only used for "is-a" relationships. Therefore an object would have to be a "A" and a "B" and a "C" before your example would work. In all other cases inheritance is not the best pattern to use. However we often seen this done anyway in real code. Many developers start using inheritance as a time saver rather than as a design pattern. This is bad and should be caught in design and code reviews.

However there are occasional cases where you can run into a situation where a class represents several different types of objects that are somehow related. For example suppose that you created a base class for editable objects (CEditableObject). You also created a separate base class for selectable objects (CSelectableObject). You then create a triagon that can be edited and selected. In C++ you'd probably use multiple inheritance to implement the class. However as you think about your design more you'll realize that interfaces better fit the bill here as editable and selectable are characteristics of a class rather than a type of class, perse. You could still create base classes to isolate out some basic implementation details but ultimately all users of an editable class care about is being able to edit the object. The same with selectable objects. Therefore to work around multiple inheritance while retaining the "is-a" relationship you'd use interfaces and optionally add an additional base class from which a selectable and editable object derive. You'd have to replicate the selection and editing code into each class that exhibited both properties. This is where interfaces in combination with aggregation come in.

2) If someone says that a class inherits an interface then they are speaking incorrectly. You don't inherit an interface. You implement an interface and inherit a base class. Yes people say this but you should correct them. I do. Inheritance indicates that the class is obtaining something. With base classes it gains all the base class members. With interfaces you don't gain anything. What you do get is a requirement to implement a specific set of features. Therefore you implement an interface's contract while you inherit a base class'es members.

3) Taking the class situation from the first comment again. Suppose we have this:

interface IEditable
{
void EditObject ( );
}

class CEditableObject : IEditable
{
public:
virtual void EditObject ( ) { ... };
}

interface ISelectable
{
void Select ( );
}

class CSelectableObject : ISelectable
{
public:
virtual void Select ( ) { ... };
}

So we have defined the standard interface/base class pattern. In this case the classes are not abstract but they could be. Now we want to implement a class that is both editable and selectable. Using multiple inheritance we'd do this:

class CSomeObject : public CEditableObject, CSelectableObject
{
}

All we've really done is exposed the ISelectable and IEditable interfaces (which our clients should be using for maintainability rather than the base classes anyway) and avoided writing additional code. In .NET we'd do this:

class CSomeObject : IEditable, ISelectable
{
private CEditableObject m_Edit = new CEditableObject();
private CSelectableObject m_Select = new CSelectableObject();

public void EditObject ( ) { m_Edit.EditObject(); }
public void Select ( ) { m_Select.Select(); }
}

This has the same effect as the earlier code but now we can change the underlying implementation in the future without worrying about breaking existing code. In the former code if some client used CEditableObject or CSelectableObject when dealing with our CSomeObject the code would break if we later removed the inheritance. With interfaces the implementation details are hidden.

Now to be fair the .NET equivalent requires more work because we have to explicitly (or implicitly) expose each interface member but this also gives us more control over how the implementation actually works. For example in the original version we'd have to override the base class method if we wanted to change how EditObject worked. In the latter code we could just implement the interface method in a different manner without touching the embedded object.

Hope this clarifies things a little more. Please be aware that this is strictly my view on the whole thing. There are people out there that still insist that C# must support multiple inheritance before it can be a true OOP language. To those people all I could say is that I'm glad I'm not on their development team. When you get to the point where you feel that something is impossible to accomplish without some language feature then you really need to take a step back and take a bigger view of the problem. In the case of multiple inheritance there is nothing that can't be accomplished with it that can't also be accomplished without it.

Michael Taylor - 1/20/07
http://p3net.mvps.org


 
 
Ramesh Kumar.S





PostPosted: Visual C++ Language, From C++ Multiple Inheritance to Interfaces. Top

class BaseClass
{
public:
void PrintName ( )
{ printf("%s", m_strName.c_str()); }

protected:
string m_strName;
};

class Derived1 : virtual public BaseClass
{
public:
Derived1 ( )
{ m_strName = "Derived1"; }

void PrintName1 ( )
{ PrintName(); }
};

class Derived2 :virtual public BaseClass
{
public:
Derived2 ( )
{ m_strName = "Derived2"; }

void PrintName2 ( )
{ PrintName(); }
};

class MultiDerived : public Derived1, public Derived2
{
};

int _tmain(int argc, _TCHAR* argv[])
{
MultiDerived cls;
cls.PrintName();
return 0;
}


The problem is solved. Multiderived will have only one copy and all public members of BaseClass will become public members of Multiderived as well the protected members becomes protected members of Multiderived.


But Following is the case:

class BaseClass
{
public:
void PrintName ( )
{ printf("%s", m_strName.c_str()); }

protected:
string m_strName;
};

class Derived1 : virtual public BaseClass
{
public:
Derived1 ( )
{ m_strName = "Derived1"; }

void PrintName1 ( )
{ PrintName(); }
};

class Derived2 :virtual private BaseClass
{
public:
Derived2 ( )
{ m_strName = "Derived2"; }

void PrintName2 ( )
{ PrintName(); }
};

class MultiDerived : public Derived1, public Derived2
{
};

int _tmain(int argc, _TCHAR* argv[])
{
MultiDerived cls;
cls.PrintName();
return 0;
}


Now what is the control over the BaseClass members under multiderived The public members of BaseClass is accessible but not the protected member of BaseClass through object of multiderived. why