了解过后,发现是一个Java泛型Trick 1 ,并且在C++中也有术语CRTP 2 ,简单的记录一下。

Java:泛型Trick

在唯一能找到的例子当中,该写法的好处是: 允许我们能够在基类/接口中定义具体子类相关的方法
在一般的Interface/BaseClass中,我们定义的无外乎是:

	public void/int/String/BaseClass/Interface xxx(void/int/String/BaseClass/Interface ..);

举个例子,有一Fruit接口,有一Apple类实现,不用泛型的写法:

public interface Fruit {
	Fruit getFruit();
// 另一个文件...
public class Apple implements Fruit {
	@Override
	public Fruit getFruit() {
		return this;

用泛型的写法:

public interface Fruit<F extends Fruit<F>> {
	F getFruit();
// 另一个文件...
public class Apple implements Fruit<Apple> {
	@Override
	public Apple getFruit() {
		return this;

可直接返回子类/使用子类参数,有效避免了instanceof等多余操作。

C++:CRTP

奇异递归模板与该Trick有异曲同工之妙,在Wiki2上解释得非常详细,这里做个简化的解释。
基本格式:

template <class T>
class Base
	// ...
class Derived : public Base<Derived>
    // ...

在Wiki中,CRTP的用途十分多样,可以类比到Java进行尝试(todo)

template <class T> 
struct Base {
    static void f() {
        T::subf();
struct Derived : Base<Derived> {
    static void subf();
// ...
void test(Base& base) {
	base.f();

基类的方法f()直接调用子类的静态方法subf()

对象计数器

template <typename T>
struct Counter {
    static int objects_created;
    static int objects_alive;
    Counter() {
        ++objects_created;
        ++objects_alive;
    Counter(const counter&) {
        ++objects_created;
        ++objects_alive;
protected:
    ~Counter() {
        --objects_alive;
template <typename T> int Counter<T>::objects_created( 0 );
template <typename T> int Counter<T>::objects_alive( 0 );
class X : Counter<X> {
class Y : Counter<Y> {

类X和类Y分别有各自不同的对象计数器,很容易理解

多态链代码过多,其作用和上述Java泛型Trick如出一辙,允许基类定义具体子类相关的方法,最终实现基类子类链式调用的效果:

	base.basef().concretef();

模板类继承接口(抽象类),通过重写接口的复制方法,实现子类的复制,可拓展到其他通用方法。
例如:

// 接口
class AbstractBase {
public:
    virtual ~AbstractBase () = default;
    virtual std::unique_ptr<AbstractBase> clone() const = 0;
// 模板基类实现AbstractBase,重写clone()方法
template <typename T>
class Base : public AbstractBase {
public:
    std::unique_ptr<AbstractBase> clone() const override {
        return std::make_unique<T>(static_cast<T const&>(*this));
protected:
   // We make clear Shape class needs to be inherited
   Base() = default;
   Base(const Base&) = default;
class C1 : public Base<C1>{};
class C2 : public Base<C2>{};
	basePtr->clone();

即可任意拷贝C1、C2的实例

  1. 见网站之More tricks with type parameters小节 ↩︎

  2. Curiously recurring template pattern,奇异的递归模板,见 Wiki ↩︎ ↩︎

目录引言Java:泛型TrickC++:CRTP静态多态对象计数器多态链多态复制引言最近碰到了如下的写法:public interface TBase&lt;T extends TBase&lt;T,F&gt;, F extends xxx&gt; { xxx}了解过后,发现是一个Java泛型Trick1,并且在C++中也有术语CRTP2,简单的记录一下。Java:泛型Trick在唯一能找到的例子当中,该写法的好处是:允许我们能够在基类/接口中定义具体子类相关的方法。在一般的Interf
stl_interfaces Boost.Iterator的iterator_facade和iterator_adaptor部分(现在称为iterator_interface )的更新的C ++ 20友好版本; C ++ 20的view_interface的C ++ 20之前版本; 还有一个名为container_interface的新模板,用于帮助创建新容器; 所有定位标准化。 该库至少需要C ++ 14。 对于迭代器部分-如果您需要编写迭代器,则iterator_interface会将其设置为: struct repeated_chars_iterator using value_type = char ; using difference_type = std:: ptrdiff_t ; using pointe
从本篇开始,我们一层一层对thrift源码进行解读。 从前文可知,Processor层是由idl编译而来,主要是进行数据流转,将协议层解析好的数据交由真正的服务去做,并将服务返回的数据交给协议层进行序列化处理。 为了保证约定的一致性,处理层的代码会在客户端和服务端被同时引入,为客户端提供代理类,为服务端提供接口供其实现。 我们先看下上一篇生成的HelloService的结构: 根据功能我们可以将其大致分为三个部分: 接口功能部分:Iface/AsyncIface/Client/As..
转载:由浅入深了解Thrift(一)——Thrift介绍与用法 转载:Thrift源码分析(八)--总结加一个完整的可运行的Thrift例子 转载:架构设计:系统间通信(11)——RPC实例Apache Thrift 上篇 转载:Thrift框架调研 一、Thrift Apache Thrift 最初是 Facebook 实现的一种支持多种编程语言、高效的远程服务器调用框架,它于 200
1. 什么是CRTP? 什么是CRTP?CRTP的全称是Curiously Recurring Template Pattern,即奇异递归模板模式,简称CRTP。CRTP是一种特殊的模板技术和使用方式,是C++模板编程中的一种惯用法。CRTP的特性表现为: 基类是一个模板类 派生类继承该基类时,将派生类自身作为模板参数传递给基类 典型代码如下: // 基类是模板类 template <typename T> class Base public: virtual ...
装逼一点的名字叫做:奇异递归模板模式 在平常开发设计类的过程中,我们常常会将两个类通用的部分抽出来,上移至一个父类,存在差异的部分在父类中定义为虚函数,在子类具体实现。 最近开发过程中,遇到一个这样的问题: 有这么一个类A: 类A里有一系列函数,是基于通过某种索引idx1获取一个值实现的 (即:这一系列函数都会调用一个叫做GetAttr(idx1) 的函数) 现有另一种索引id 这里将基类转换成派生类用的是static_cast静态绑定,而普通基类转派生类用的是dynamic_cast动态绑定。 动态绑定的目的是为了确保你所转化的派生类是正确的,而对于CRTP来说,基类是继承于模板类的参数,也就是派生类本身。 这也正是CRTP这种设计的目的。 2.CRTP的优点 多态是个很好的特性,但是动态绑定比较慢,因为要查虚函数表。eg: 2.轻松地实现各个子类实例创建和析构独立的计数 3.多态链(Polymorphic