Ну, так как я запустил подход Decorator, я мог бы также:)
РЕДАКТИРОВАТЬ: давайте добавим AddOnValues для решения это , а также
Проблема здесь в мульти-наследовании. Отслеживать такую диаграмму непросто, но если вы присмотритесь, вы увидите, что CMyClass<AddOn_A>
дважды наследуется от CBase.
CMyClass<AddOn_A>
<- <code>AddOn_A<CBase> <- <code>CBase
CMyClass<AddOn_A>
<- <code>CMyclass<empty,empty,empty> <- <code>CBase
Проблема в том, что вы использовали подход политики, а не подход декоратора. При правильном подходе Decorator иерархия строго линейна, и у вас есть только один параметр шаблона за раз. Давайте получим основу:
// Note that the static_cast are completely unnecessary
// If you inherit from T then you can freely enjoy
// its public and protected methods
template< class T >
class AddOn_A : public T
{
public:
enum { AddOnValues = T::AddOnValues | 0x01 }; // this hides T::AddOnValues
AddOn_A( int x ) : T( x ) {};
int AddOne()
{
return this->GetValue() + 1;
};
};
template< class T >
class AddOn_B : public T
{
public:
enum { AddOnValues = T::AddOnValues | 0x02 }; // this hides T::AddOnValues
AddOn_B( int x ) : T( x ) {};
int AddTwo()
{
return this->GetValue() + 2;
};
};
class CBase
{
public:
enum { AddOnValues = 0x00 };
explicit CBase( int x ) : x_( x ) {}
virtual ~CBase() {} // virtual destructor for inheritance
int GetValue() const { return x_; }; // const method
private:
int x_;
};
Теперь мы можем перейти к фактическому использованию!
// First, the typedef approach
typedef AddOn_B< AddOn_A< CBase > > CMyClass;
CMyClass myObject(3);
std::cout << myObject.GetValue() << std::endl;
std::cout << myObject.AddOne() << std::endl;
std::cout << myObject.AddTwo() << std::endl;
Довольно просто, не правда ли? Очевидным недостатком является то, что вы не добавляете туда функциональность ...
// I want more!
template < class T >
class CMyClassImpl: public T
{
// Whatever you want
};
CMyClassImpl< AddOn_B< AddOn_A< CBase > > > myObject(3);
Хорошо ... не так красиво, я думаю ... Еще лучше? Ну, мы можем просто использовать обертку!
// Even better
template <>
class CMyClass: public CMyClassImpl < CBase > {};
template < template <class> class AddOn1>
class CMyClass: public CMyClassImpl <AddOn1 < CBase > > {};
template < template <class> class AddOn1,
template <class> class AddOn2 >
class CMyClass: public CMyClassImpl < AddOn2 < AddOn1< CBase > > > {};
template < template <class> class AddOn1,
template <class> class AddOn2,
template <class> class AddOn3 >
class CMyClass: public CMyClassImpl < AddOn3 < AddOn2< AddOn1< CBase > > > > {};
// Go on with as much specializations as you wish
CMyClass < AddOn_A, AddOn_B > myObject(3);
Конечно, последнее решение экономит набор текста на вызывающем сайте, но вы действительно должны работать над своим классом:)
Кроме того, вы должны повторять различные конструкторы на каждом шаге наследования, что мне быстро докажет ... скучно.
Существуют макросы препроцессора, но ... в прошлый раз мне понадобилось около 500 строк, чтобы сгенерировать что-то довольно простое, так что не беспокойтесь и не печатайте, действительно:)