Reputation: 927
Following is a model example. Suppose I have class Creature
that has three coordinates x,y,z. I also have inheritance tree:
class Creature {
int x;
int y;
int z;
};
class Mammal : public Creature {common code for mammals};
class Wolf : public Mammal;
class Bat : public Mammal;
class Birds : public Creature {common code for birds};
class Penguin : public Bird;
class Crow : public Bird;
Some creatures can fly, so they should have following member function (implementation is same for all creatures):
void fly(int height) {z = height;}
So I do the following:
class FlyingMammal : public Mammal {
void fly(int height) {z = height;}
//'z' is also used in some methods of non-flying creatures,
//so it can't be moved to FlyingMammal class.
};
class Wolf : public Mammal;
class Bat : public FlyingMammal;
class FlyingBird : public Bird {
void fly(int height) {z = height;}
};
class Penguin : public Bird;
class Crow : public FlyingBird;
However, I have code duplication in FlyingMammal and FlyingBird. Is there standard pattern to avoid it? I suppose some kind of multiple inheritance might fit here, but don't know how exactly to do it.
Note that additional interface like fly()
does not introduce new data members, only new member functions. But it uses member data z
of Creature
class.
Upvotes: 2
Views: 260
Reputation: 436
I think Curiously recurring template pattern would be one way to go ... like so
template <typename TThisClass>
class Flier
{
public:
void fly(int z) { static_cast<TThisClass *>(this)->setZ(z); }
};
class Creature {
private:
int x;
int y;
int z;
public:
void setX(int x) { this->x = x; }
void setY(int y) { this->y = y; }
void setZ(int z) { this->z = z; }
// add setter & getter for x, y, z
};
class Mammal : public Creature { /*common code for mammals*/};
class Wolf : public Mammal { };
class Bat : public Mammal, public Flier<Bat> { };
class Bird : public Creature { /*common code for birds*/ };
class Penguin : public Bird { };
class Crow : public Bird, public Flier<Crow> { };
int main(int, char **) { Crow c; c.fly(1000); };
Upvotes: 2