Skip to content

Instantly share code, notes, and snippets.

@astanin
Last active May 28, 2016 18:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save astanin/3f67284fed7ab3e53b022d7fe34c3a55 to your computer and use it in GitHub Desktop.
Save astanin/3f67284fed7ab3e53b022d7fe34c3a55 to your computer and use it in GitHub Desktop.
How to share implementation of methods between multiple derived classes in C++ without putting it into the base class. Using the curiously recurring template pattern.
#include <iostream>
/* How to share implementation of methods between multiple derived classes
without putting it into the base class. Using the curiously recurring template
pattern.
Let's assume, that most, but not all of the derived classes are implemented in
a similar way, and have .x and .y members.
It makes sense to write getters and setters only once and share this code
between all implementations.
Unfortunately, if some of the classes in the hierarchy don't have .x and .y,
we can't put implementation of the getters in the Base class. */
class Base {
public:
virtual int getX() const = 0;
virtual int getY() const = 0;
};
/* Instead we may put the shared implementation into a derived template
class BaseWithGetters which may use template parameter to cast this pointer to
the final class type. */
template<typename HasXY>
class BaseWithGetters : public Base {
public:
virtual int getX() const {
return static_cast<const HasXY*>(this)->x;
}
virtual int getY() const {
return static_cast<const HasXY*>(this)->y;
}
};
/* Final classes which share implementation should be derived from the
template class BaseWithGetters rather than Base. */
class DerivedA : public BaseWithGetters<DerivedA> {
public:
/* Unfortunately, we have to break encapsulation to allow access to .x and .y
from the base class BaseWithGetters<>. So these implementation details should
be public. */
int x;
int y;
public:
DerivedA() : x(1), y(2) {}
};
class DerivedB : public BaseWithGetters<DerivedB> {
public:
int x;
int y;
public:
DerivedB() : x(10), y(20) {}
};
/* Final classes which implement virtual method in a different way,
should be derived from Base class directly. */
class DerivedNoXY : public Base {
public:
virtual int getX() const { return 100; }
virtual int getY() const { return 200; }
};
int main() {
DerivedA a;
DerivedB b;
DerivedNoXY c;
std::cout << "DerivedA.getX() should return 1: " << a.getX() << "\n";
std::cout << "DerivedA.getY() should return 2: " << a.getY() << "\n";
std::cout << "DerivedB.getX() should return 10: " << b.getX() << "\n";
std::cout << "DerivedB.getY() should return 20: " << b.getY() << "\n";
std::cout << "DerivedNoXY.getX() should return 100: " << c.getX() << "\n";
std::cout << "DerivedNoXY.getY() should return 200: " << c.getY() << "\n";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment