目录

​RAII(Resource Acquisition Is Initialization)​

​ScopeGuard​

​NVI(Non-Virtual Interface)​

​CRTP(Curiously Recurring Template Pattern)​

​PIMPL(Private Implementation)​


RAII(Resource Acquisition Is Initialization)

即资源获取就是初始化,是一种管理资源的机制。

如管理new操作符的资源:

class A
{
public:
int *p;

A(int n)
{
p = new int[n];
}
~A()
{
delete p;
}
};

int main()
{
A a(10);
// a.p
return 0;
}

只写了一个简单的示例。

一个经典的案例:lock_guard类,源代码如下

// CLASS TEMPLATE lock_guard
template<class _Mutex>
class lock_guard
{ // class with destructor that unlocks a mutex
public:
using mutex_type = _Mutex;

explicit lock_guard(_Mutex& _Mtx)
: _MyMutex(_Mtx)
{ // construct and lock
_MyMutex.lock();
}

lock_guard(_Mutex& _Mtx, adopt_lock_t)
: _MyMutex(_Mtx)
{ // construct but don't lock
}

~lock_guard() noexcept
{ // unlock
_MyMutex.unlock();
}

lock_guard(const lock_guard&) = delete;
lock_guard& operator=(const lock_guard&) = delete;
private:
_Mutex& _MyMutex;
};

实例化的时候加锁,生命周期结束的时候自动解锁。

ScopeGuard

这个方法是定义一个ScopeGuard模板类,用于管理临时使用的资源。

把临时资源的释放操作写成lambda表达式,申请ScopeGuard实例存放这个表达式,实例生命周期结束时自动

代码:

template <typename Lambda>
class ScopeGuard
{
public:
ScopeGuard(Lambda &&lam): lambda (lam) {
}
~ScopeGuard() {
lambda();
}
private:
Lambda lambda;
};

template <typename T>
ScopeGuard<T> GetScopeGuard(T &&lambda)
{
return ScopeGuard<T>(move(lambda));
}

int main()
{
int* p = new int[100];
GetScopeGuard([&] {delete[] p; });
return 0;
}

NVI(Non-Virtual Interface)

NVI是用非虚函数调用虚函数,把非虚函数作为接口。

class A
{
public:
void show()
{
cout << "A\n";
print();
}
virtual void print() {};
};
class B :public A
{
public:
void print()
{
cout << "x=" << x;
}
private:
int x;
};

int main()
{
B b;
b.show();
return 0;
}

CRTP(Curiously Recurring Template Pattern)

奇异的递归模板模式,指的是子类继承一个模板类,模板的特化类型是子类本身。

最简代码:

#include<iostream>
using namespace std;

template<typename T>
class Base
{
public:
void virtualFunc()
{
static_cast<T*>(this)->realFunc();
}
};

class Chird :public Base<Chird>
{
public:
void realFunc()
{
cout << "real func";
}
};

int main()
{
Chird().virtualFunc();
return 0;
}

这个简单的例子就能看出CRTP的写法,也能看出,其实本质上静态多态。

CRTP的好处是,静态多态比继承虚函数的动态多态要快。

应用:

​CRTP单例模板​

​CRTP + 模板方法模式​

PIMPL(Private Implementation)

通过一个私有的成员指针,将指针所指向的类的内部实现全部隐藏。

普通代码:

class A
{
public:
int f(int n)
{
return f1(n) + n + f2(n);
}
private:
int f1(int n)
{
return n * n * n;
}
int f2(int n)
{
return n > 0 ? 1 : -1;
}
};

PIMPL代码:

class B;
class A
{
public:
A()
{
opt = new B();
}
int f(int n)
{
return opt->f1(n) + n + opt->f2(n);
}
private:
B* opt;
};

class B
{
public:
int f1(int n)
{
return n * n * n;
}
int f2(int n)
{
return n > 0 ? 1 : -1;
}
};