关于c ++:奇怪的重复模板模式时间两个

Curiously Recurring Template Pattern times two

我有一般设计问题。我正试图实现这样的功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
                  ------------
                  |Base Class|
                  ------------
                       |
               ------------------
               |                |
          -----------      -----------
          |SubClass1|      |SubClass2|
          -----------      -----------
               |                |
         --------------   --------------
         |SubSubClass1|   |SubSubClass2|
         --------------   --------------

当基类提供虚拟函数时,子类将实现分类,子类将常量提供给实现。

我考虑过两次使用"奇怪的重复模板模式",如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 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()。

有没有更好的方法可以做到这一点?

提前多谢。


这样做很好,我看不出这样做的任何一般缺点。我只是不知道您实际使用crtp的位置,以及为什么简单的虚拟继承对于您的用例不起作用(crtp通常被用作静态多态性)。

也不要明白你的意思

1
private1(double, double);

在你的subclass1中,你的意思是构造器吗?就目前而言,它不会在实例化时编译(除了构造函数或析构函数之外,不允许没有返回值的函数)。

另一个批评是:如果您指的是常量,那么应该在子类中声明conststatic const成员。

由于您没有明确指定您的特定用例,很难说什么才是它的最佳设计。我可以提供从尝试遵循您的想法中获得的另一种选择:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 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) {
        // ...
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
// 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
    }
};
1
2
3
4
5
6
7
// 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模板参数上的静态接口("traits")检查替换它们。