0

I am looking for an optimal way of implementing the code common between subset of interface implemtations. To describe it concretely assume we have an interface P that is implemented by A, B and C. Again, assume A and B have certain common functionality (common code), B and C have certain common functionlity and similarly A and C have common functionality in the implementation of the interface. I understand that:

  1. We can make intermediate class for each pair, containing the common functionality and then derive the classes from the intermediate classes, e.g., intermediate class AB implementing common code between A and B and BC for common code between B and C and then derive B from AB and BC.
  2. Replicate the code for the classes in each pair

1 should theortically be the optimal solution, however, practially it can create a huge mess because actually I don't just have 3 classes implementing the interface but a large number of them. Moreover, the common functionalities are not just between pairs but large subsets of the classes and there are many such subsets. Hence, we will need to have a large number of intermediate classes to implement the common functionality between different subsets. This makes it hard/inefficient to implement through intermediate classes, as we require large number of these intermediate classes.

I believe 2 is also not the best solution, because it requires code replication, which will cause the problems of code maintanance.

Edit: I have tried to simplify the question to give a clear picture in response to the comments.

user2219907
  • 33
  • 1
  • 6
  • Inheritance should be used for interfaces/substitution. Does `P` describe an interface implemented by the child classes? – Mark B Jul 29 '13 at 18:42
  • 4- Use an interface, you can have a function that take this interface as parameter to do the common code – the_lotus Jul 29 '13 at 18:45
  • Unless you are going to look at arbitrary B and Cs to do X, arbitrary A and Bs to do Y, and A, B and C's to do Z, than you'd probably rather composition than inheritance. – IdeaHat Jul 29 '13 at 18:47
  • Does the functionality involve interface features which P lacks? – Beta Jul 29 '13 at 19:21
  • Give us a use case, because I don't really see the problem with the solution you've outlined. If there's functionality common to A and B and not available to anyone but A and B you should express that dependency in some way. If I collect the common functionality between A and B together into AB what way is it not properly expressive for AB to be either inherited (privately?) or aggregated (private member?) into A and B? – Speed8ump Jul 29 '13 at 21:13
  • (I believe you are refering to intermediate classes solutions) So you are right that it does serve the purpose but only when we have a few derived classes. If the number of derived classes is large and different subsets have different common codes then making these intermediate classes will itself become a big overhead. There will be many such intermediate classes for each common functionality of a subset. Hence, its not a wrong solution but it is simply too messy! Hence, I posted the question here. May be someone has a clever solution for this... – user2219907 Jul 29 '13 at 21:41
  • If the functionality involves the interface, then this might be a case where multiple inheritance make sense. Otherwise, there are design patterns involving composition that would be better. – Beta Jul 30 '13 at 01:27
  • http://stackoverflow.com/a/16648036/412080 answers your question – Maxim Egorushkin Jul 30 '13 at 07:21

1 Answers1

0

You can define your common implementations within template functions, and call them as desired from each class to implement the interface function.

Using your interface P, classes A, B, and C, it gives the following.

struct P {
    virtual int X() = 0;
};

template <typename T>
int CommonAB( T const & t ) { return t.x; }

template <typename T>
int CommonBC( T const & t ) { return t.y; }

template <typename T>
int CommonCA( T const & t ) { return t.x+t.y; }


struct A : public P {
    int X() { return CommonAB( *this )+CommonCA( *this ); }
protected:
    int x;
    int y;
friend int CommonAB<A>( A const & );
friend int CommonCA<A>( A const & );
};

struct B : public P {
    int X() { return CommonBC( *this )+CommonAB( *this ); }
protected:
    short x;
    short y;
friend int CommonBC<B>( B const & );
friend int CommonAB<B>( B const & );
};

struct C : public P {
    int X() { return CommonCA( *this )+CommonBC( *this ); }
protected:
    char x;
    char y;
friend int CommonCA<C>( C const & );
friend int CommonBC<C>( C const & );
};


int main()
{
    A a;
    B b;
    C c;

    a.X();
    b.X();
    c.X();

    return 0;
}
Didier Trosset
  • 36,376
  • 13
  • 83
  • 122