Любопытно повторяющийся шаблон Pattern раза два

У меня есть общий вопрос дизайна. Я пытаюсь реализовать что-то вроде этого:

                  ------------
|Base Class|
------------
|
------------------
|                |
-----------      -----------
|SubClass1|      |SubClass2|
-----------      -----------
|                |
--------------   --------------
|SubSubClass1|   |SubSubClass2|
--------------   --------------

где базовый класс предоставляет виртуальные функции, подклассы — реализацию, а подклассы — предоставляют константы реализациям.

Я подумал об использовании «Любопытно повторяющегося шаблона» дважды, как это:

// header baseclass.h
template <typename subclass>
class baseclass {
private:

public:

virtual double GetQuantity1(double given1, double given2) = 0;

virtual double GetQuantity2(double given1) = 0;

}

// header subclass1.h
template <typename n>
class subclass1:public baseclass<subclass>{
private:

private1(double, double);

public:

double GetQuantity1(double given1, double given2);

double GetQuantity2(double given1);

}

// header subsubclass1.h
class subsubclass1:public subclass1<subsubclass1>{
private:

public:

double constant1;

double constant2;
}

Затем я бы вызвал Subsubclass :: GetQuantity1 () при использовании кода.

Это что-то вроде кошерной вещи или есть лучшие способы сделать что-то подобное?

Заранее большое спасибо.

1

Решение

Это нормально, и я не вижу никакого общего недостатка в этом. Я просто не понимаю, где вы на самом деле используете CRTP и почему простое виртуальное наследование не будет работать в вашем случае использования (CRTP обычно используется как статический полиморфизм).

Также не понимаю, что вы имеете в виду

private1(double, double);

в вашем subclass1 Вы имели в виду конструктор? В нынешнем виде он не будет компилироваться при создании экземпляра (функции не допускаются без возвращаемого значения, кроме конструкторов или деструкторов).

Другой критик будет: если вы имеете в виду константы, вы должны объявить const или же static const члены в ваших подклассах.

Поскольку вы не можете четко указать конкретный вариант использования, трудно сказать, что действительно будет лучшим дизайном для него. Я могу просто предоставить альтернативу, уловленную попыткой следовать вашим мыслям:

// header baseclass.h
template <typename subclass>
class baseclass {
public:

inline double GetQuantity1(double given1, double given2) {
// may be add a static check for GetQuantity1_Impl with a traits
// check on subclass.
return static_cast<subclass*>(this)->GetQuantity1_Impl(given1,given2);
}

inline double GetQuantity2(double given1) {
return static_cast<subclass*>(this)->GetQuantity2_Impl(given1);
}

// You also can provide default implementations, otherwise the interface
// method will be required from subclass to compile correctly
inline double GetQuantity1_Impl(double given1, double given2) {
// ...
}
};

// header subclass1.h
template<double const1, double const2>
class subclass1:public baseclass<subclass1>{
public:
subclass1() {}

double GetQuantity1_Impl(double given1, double given2) {
return 0.0; // Apply formula using the constants instead of 0.0
}
double GetQuantity2_Impl(double given1) {
return 0.0; // Apply formula using the constants instead of 0.0
}
};

// Client implementation file
// No need for subsubclass1 just instantiate for usage

subclass1<0.3, 3.1415> myAlgo;
// A client calls the public interface of the (implicit) base class
double result1 = myAlgo.GetQuantity1(23.2,42);
double result2 = myAlgo.GetQuantity2(2.71828);

Исключите определения чисто виртуальных методов в базовом классе и замените их статической проверкой интерфейса («черты») на subclass параметр шаблона.

3

Другие решения

Других решений пока нет …