views:

176

answers:

4

I have trouble when designing classes like this

class C1 {
public:
  void foo();
}

class C2 {
public:
  void foo();
}

C1 and C2 has the same method foo(),

class Derived1 : public Base {
public:
  void Update() {
    member.foo();
  }
private:    
  C1 member;
}

class Derived2 : public Base {
public:
  void Update() {
    member.foo(); 
  }
private:    
  C2 member;
}

Update() of both Derived class are exactly the same, but the type of member is different. So i have to copy the Update implement for every new derived class.

Is that a way to reduce this code duplication? I only come out with a solution with macro. I think there is a more elegant way to solve this with template but I can not figure it out..

EDIT: thanks a lot guys but i think i missed something..

1.I'm using c++

2.In reality each Derived class has about 5 members, they all afford the foo() method and are derived from the same base class. My situation is that i have already written a (very long) Update() method and it can work for every derived class without any modification. So i just copy and paste this Update() to every new class's Update() and this lead to terrible code duplication. I wonder if there is a way in which i need not to rewrite the Update() too much and can reduce the duplication.

thx again

A: 

If you have the control over C1 and C2, you can either define a base class or an abstract base class and handle it at Base class or third helper class.

eed3si9n
+6  A: 

This is exactly the sort of application that class templates are designed for. They allow functions within a class to operate on different data types, without the need to copy algorithms and logic.

This Wikipedia page will give you a good overview of templates in programming.

Here's the basic idea to get you started:

template  <class T>
class CTemplateBase
{
public:
    void Update()
    {
        member.foo();
    }
private:
    T member; // Generic type
}

class CDerived1 : public CTemplateBase<C1>
{
    // No common algorithms required here
}

class CDerived2 : public CTemplateBase<C2>
{
    // No common algorithms required here
}
LeopardSkinPillBoxHat
Instead of those derived's, why not just: "typedef Dervied1 CTemplateBase<C1>;" and "typedef Dervied2 CTemplateBase<C2>;" (obviously derived is no longer a good name, but you get the point).
@ilproxil - Yeah, I guess that's acceptable. But I'll leave it as it is for clarity purposes.
LeopardSkinPillBoxHat
A: 

Move the method to the parent class:

class IFooable {
public:
  virtual void foo() = 0;
}

class C1 : IFooable {
public:
  void foo();
}

class C2 : IFooable {
public:
  void foo();
}

class Base {
public:
  void Update() {
    member->foo(); 
  }
private:    
  IFooable* member
}

class Derived1 : public Base {
  Derived1 () : member(new C1()) {}
  ~Derived1 () { delete member; }
}

class Derived2 : public Base {
  Derived2 () : member(new C2()) {}
  ~Derived2 () { delete member; }
}
Nick Whaley
This is C++, not C#. The member will will need to be a pointer, not an instance. Not only will the polymorphism not work, this wouldn't compile. I think you're on the right track though, and I prefer this to the template solution (though I have trouble coming up with a non-subjective reason).
Andrew Shepherd
Thanks, its been awhile on my C++. member has been changed to a pointer.
Nick Whaley
IFooable also needs a virtual destructor if you're going to delete pointers of type IFooable*.
Steve Jessop
A: 

If your Drived1 and Derived2 are same except for the type (C1 and C2) of member, then you can consider using a single class Derived and a template. (Excuse my syntax if incorrect, i m C# dev :D )

template <class T>
class Derived : public Base {
public:
  void Update() {
    member.foo();
  }
private:    
  T member;
}

Something on the above lines.

Rashmi Pandit