C++ 设计NVI(Non-Virtual Interface)

举报
用户已注销 发表于 2022/06/10 23:56:13 2022/06/10
1.2k+ 0 0
【摘要】 目录 RAII(Resource Acquisition Is Initialization) ScopeGuard NVI(Non-Virtual Interface) CRTP(Curiously Recurring Template Pattern) PIMPL(Private Implementation) ...

目录

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;
      	}
      };
  
 

文章来源: blog.csdn.net,作者:csuzhucong,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/nameofcsdn/article/details/125222648

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。