views:

192

answers:

9

Hi all,

I have two classes that are almost identical, besides one method. The classes have the same data part and all the member functions but one:

class A {
private:
  double data;
public:
  double calc(){
     return data*data;
  }
   double especific(){
     return 2.0*data;
  }
 }

and the second class is identical, besides the especific method.

This member function in particular needs all the member data to calculate, so passing by value or reference is not an option. Is there a way to implement this without a lot of code duplication? Either using only one class or using templates, but not inheritance (huge performance impact).

Thanks

EDIT: Thanks for all the responses. The Strategy pattern can help in my case, I will try it and see if it works. I'm avoiding virtual inheritance as the plague based on some tests that I did in a different program. This routine will be called everywhere, and performance is a very important factor.

+2  A: 

have a base class with all the common stuff and derive the two classes from it

As others have pointed out

a) this is exactly what inheritance was designed for

b) there is no perfomance overhead whatsoever

c) there are no nasty gotchas lurking anywhere

Many people will comment on this and say 'ah but what about xxxx'; these will be valid comments for advanced and corner case use; except you are not going to do any of them based on the simplicity of what you asked for.

pm100
Thanks for your answer, but I think I am at the corner case. I just wrote a (very) simplified version of my problem.
Ivan
+2  A: 

Maybe I'm missing the point but why not have a base class that implements all the common functionality and a pure virtual especific() and then inherit this and have the child classes implement especific() as required. Make the data member protected.

class BaseA 
{ 
protected: 
  double data; 
public: 
  double calc(){ 
     return data*data; 
  } 
   virtual double especific() = 0;
};

class A1 : BaseA
{
   double especific()
   {
     return data * 2;
   }
};

WRT to the huge performance impact of inheritance... I think this isn't likely unless the cost of vtable lookups is significant compared with the work being done in the method body and you're doing this in a tight loop what's consuming most of your application processing.

Ade Miller
That's exactly my situation: inside a tight loop being called millions of times...
Ivan
A: 

I have a feeling that a Bridge pattern might be a good approach for you as it sounds like you want to have unique implementations for your common abstraction.

hydrogen
A: 

There are several ways to do this, many of which you've named:

  • Inheritance from a common base class (which does most of the work), and virtual especific()
  • One class, with two slightly differently-named especific() methods (or overloaded methods)
  • Use template specialisation
  • Have A and B use some other class C to do the majority of the work.

There may be others.

You'll need to choose one of these based on the semantics of your classes and application, and any other specific constraints or requirements.

Oli Charlesworth
+3  A: 

This sounds like a job for the Strategy pattern. It can be implemented in this case as a template parameter. Often it would be implemented as a constructor parameter or a setter method on the class, but that would require inheritance to work properly.

In this case, something like:

template <class SpecificStrategy>
class A {
 private:
    double data;
 public:
    double calc(){
       return data*data;
    }
    double especific() {
       return SpecificStrategy::especific(data);
    }
};

class DoubleStrategy {
   static double especific(double data) {
      return 2 * data;
   }
};
class TripleStrategy {
   static double especific(double data) {
      return 3 * data;
   }
};

Then you can refer to:

A<DoubleStrategy> x;
A<TripleStrategy> y;

x and y will be of completely unrelated types, but it sounds like that's not what you want in this case.

Now, in my opinion using a virtual function and inheritance is the way to go. As someone else pointed out, the performance penalty isn't that large. However there are circumstances in which I could see that it would be a bad idea.

For example, if this class is intended to represent a vector in a graphics package and you're going to be doing the same transform to millions of them, then I could see how you would not want a virtual function call to be a part of the code that did the transform. In fact, you would want to avoid pointer dereferences of any kind of you could at all help it.

Omnifarious
Good answer; as a side note, I often get a chuckle out of people tagging this or that technique a "pattern." Are patterns considered to be inventions _of_ people, or are they considered observations _by_ people? Because what you call "strategy pattern," I call "functional programming."
San Jacinto
@San Jancinto - Ideally a pattern is an observation of a structure that shows up over and over again. :-)
Omnifarious
@San Jacinto: usually, a pattern is nothing more than a convoluted and overcomplicated way to approximate functional programming in an imperative language. :)
jalf
But it isn't equivalent of using a virtual method. If you graphics package is using a container into which user can add objects of different types, then you have to use abstract base class.
doc
Interesting response! The problem now is that I cannot make a vector<A> with the two different types that I've just created.
Ivan
@Ivan - if you need to do that, the Strategy pattern and inheritance is your best option. All other options will be slower, or at least no faster.
Omnifarious
+1  A: 

Check out the Strategy Pattern

You could have your class take a functor which especific then calls. You can supply different functors for different ways of calculating the output. There are several other ways you can implement Strategy as well.

Lima Beans
+2  A: 

If you don't make any members virtual and define your classes intelligently there should be no performance impact whatsoever from inheritence.

All inheritence is saying is "make this class like that one, but with this extra stuff". It is no different at runtime than if you'd typed the same stuff twice.

I suppose you could make a performance impact by doing a bunch of unnesscary stuff in the constructor for the parent class that the child classes don't need. But you won't be that stupid. I have faith in you.

T.E.D.
Thanks for the faith! ;-) But is the use of a compile time template faster than using inheritance?
Ivan
@Ivan - No. Why would it be? There's no reason for the code generated to be any different. The only real difference is that the template may take longer to compile, and be tougher to debug.
T.E.D.
+1  A: 

Why two classes at all? If the classes share the same data, you may just want to implement both functions in one class.

class A {
private:
  double data;
public:
  double calc(){
     return data*data;
  }
   double especific(){
     return 2.0*data;
  }
   double eMoreSpecific() {
     return 23.0*data;
 }
InsertNickHere
A: 

check out the "inheritance pattern"