引言
奇异递归模板模式(Curiously Recurring Template Pattern,简称 CRTP),也被称为奇异模板,是 C++ 中的一种模板编程技术。它允许基类使用派生类的类型信息,实现了一种编译时多态。
奇异递归模板模式
奇异递归模板是一种利用模板技术实现的编译时多态,允许一个类在调用函数的时候实现不同的方法。
实现方法:
- 基类使用模板类,模板参数代表了派生类类型
- 函数里将基类指针(this)转为派生类指针并调用派生类的实现方法,达到对于传入的不同派生类实现不同的方法。
- 派生类要继承基类,并将自己的类型传入到模板参数当中
代码实现
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
|
// 基类模板
template <typename Derived>
class Shape {
public:
void draw() {
std::cout << "所有类型draw的公用代码" << std::endl; //进行复用,不用每个类型都写一份
static_cast<Derived*>(this)->drawImpl();
}
};
// 派生类:Circle
class Circle : public Shape<Circle> {
public:
void drawImpl() {
std::cout << "Drawing a circle." << std::endl;
}
};
// 派生类:Square
class Square : public Shape<Square> {
public:
void drawImpl() {
std::cout << "Drawing a square." << std::endl;
}
};
int main() {
Circle circle;
Square square;
circle.draw();
square.draw();
}
|
奇异模板特性
特点
通过函数调用实现多态
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
|
template <typename Derived>
class Shape {
public:
void draw() {
std::cout << "shared draw" << std::endl;
static_cast<Derived*>(this)->drawImpl();
}
};
// 派生类:Circle
class Circle : public Shape<Circle> {
public:
void drawImpl() {
std::cout << "Drawing a circle." << std::endl;
}
};
// 派生类:Square
class Square : public Shape<Square> {
public:
void drawImpl() {
std::cout << "Drawing a square." << std::endl;
}
};
template<typename Shape>
void Draw(Shape& shape) {
shape.draw();
}
int main() {
Circle circle;
Square square;
Draw(circle);
Draw(square);
}
|
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
|
class Shape {
public:
void draw() {
std::cout << "所有类型draw的公用代码" << std::endl;
drawImp();
}
virtual void drawImp() = 0;
};
class Circle : public Shape {
public:
void drawImp() {
std::cout << "Drawing a circle." << std::endl;
}
};
class Square : public Shape {
public:
void drawImp() {
std::cout << "Drawing a square." << std::endl;
}
};
void Draw(Shape* shape) {
shape->draw();
}
int main() {
Shape* circle = new Circle;
Shape* square = new Square;
Draw(circle);
Draw(square);
}
|