3

Please refer the following example.

using namespace std;
//Base interface
class IBase
{
public:
    virtual void BaseMethod1() = 0;

    virtual void BaseMethod2() = 0;
};

class IEntity1 : public IBase
{
public:
    virtual void Entity1Method1() = 0;

    virtual void Entity1Method2() = 0;
};

class Entity1 : public IEntity1
{
public:
    Entity();
//IBaseMethods
    void BaseMethod1();
    void BaseMethod2();
//IEntityMethods
    void Entity1Method1();
    void Entity1Method2();
//EntityMethods
    void Method1();
    void Method2();
};

In the above example, for all other entities deriving from IBase needs to implement BaseMethod1() and BaseMethod2().Because of which lots of code duplication is happening? Is there anyway where we can avoid redundant implementation of IBase methods in entities deriving from it?

Jan Hudec
  • 73,652
  • 13
  • 125
  • 172
  • 5
    if you don't make them pure virtual and instead have them as normal virtual functions with a default implementation in the base class. – AndersK Feb 10 '14 at 05:08
  • Hi, Thanks for the response. It is a sample example from a c++ cli implementation. And because it is an interface base approach, we are not exposing any behavior. So making them pure virtual is the thing to do. Any other way than making it normal virtual functions? – user3291406 Feb 10 '14 at 05:26
  • A bit offtopic, but why is there a `using namespace std` in the example? :) – rozina Feb 10 '14 at 07:52
  • C++ does not have interfaces, it has full multiple inheritance. Using abstract base classes instead of pure interfaces is appropriate there. And the fact it is c++cli does not matter when you are defining plain classes; it only matters for the special `__gc class`es that only have single inheritance plus interfaces. – Jan Hudec Feb 10 '14 at 08:11

4 Answers4

0

You can use virtual inheritance in combination with a default base implementation class to encapsulate your default base behavior, and have it be only inherited by the concrete classes you want, like follows:

using namespace std;
//Base interface
class IBase
{
public:
    virtual void BaseMethod1() = 0;
    virtual void BaseMethod2() = 0;
};

class IEntity1 : virtual public IBase
{
public:
    virtual void Entity1Method1() = 0;
    virtual void Entity1Method2() = 0;
};

class BaseImpl : virtual public IBase
{
public:
    virtual void BaseMethod1()
    {
        ...
    }
    virtual void BaseMethod2()
    {
        ...
    }
}

class Entity1 : public IEntity1, public BaseImpl
{
public:
    Entity1();
//IEntityMethods
    void Entity1Method1();
    void Entity1Method2();
//EntityMethods
    void Method1();
    void Method2();
};

There is, however, a runtime cost associated with virtual inheritance. Multiple inheritance also comes with some structural issues, e.g. base class construction.

You can even have some fun with template classes to make your class composition more modular:

template<typename TEntity, typename TBaseImpl>
class ConcreteEntity: public TEntity, public TBaseImpl
{
public:
    ConcreteEntity() {}
};

class ConreteEntity1 : public ConcreteEntity<IEntity1, BaseImpl>
{
public:
    ConreteEntity1();

//IEntityMethods
    void Entity1Method1();
    void Entity1Method2();
//ConreteEntity1 Methods
    void Method1();
    void Method2();
};
Community
  • 1
  • 1
Martin J.
  • 5,028
  • 4
  • 24
  • 41
0

You could make a function that is called in BaseMethod1() implementations that are the same.

Something like this:

void BaseMethod1_common();

class Entity1 : public IEntity1
{
public:
    Entity();
//IBaseMethods
    void BaseMethod1() { BaseMethod1_common(); }
    void BaseMethod2();
//IEntityMethods
    void Entity1Method1();
    void Entity1Method2();
//EntityMethods
    void Method1();
    void Method2();
};
rozina
  • 4,120
  • 27
  • 49
0

First of all IBase deserves a virtual destructor.

Declare it pure virtual and define IBase:BaseMethod1() and IBase::BaseMethod1().

jimifiki
  • 5,377
  • 2
  • 34
  • 60
0

If your intention is to hide implementation, then the only option would be to release the code as a library and then share only the header file among the other developers.

Implementing a global function, or using multiple inheritance as suggested still mean that your implementation is exposed.

However, if the intent is to reduce coupling among the various classes, there's another option :

  • Create a class that has the actual shared implementation, and then another class which will be an interface to it.
  • This interface class will then be the base class for other derived entities.

Example code is shown below :

//First Header and Cpp file
class Base_private
{
public:
    BaseImpl(arguments);
    ~BaseImpl();

    void BaseMethod1() {
        //Implementation
    }
    void BaseMethod2() {
        //Implementation
    }
};

//Second Header and Cpp file
class BaseInterface
{
public:
    BaseInterface(arguments);
    ~BaseInterface();

    void BaseMethod1() {
        m_pBase->BaseMethod1();
    }
    void BaseMethod2() {
        m_pBase->BaseMethod2();
    }
private:
    Base_private* m_pBase;
};

class Entity : public BaseInterface
{
public:
    Entity(arguments);
    ~Entity();

    void Method1();
    void Method2();
};
jlouzado
  • 442
  • 3
  • 17