公私分明
应用场景
C++交付sdk库的时候,需要同时给出头文件。但是C++的类存在一个问题:private是类内部使用的,可能会包括不想暴露给用户的敏感成员函数和数据。但是对于C++来说,无论是public还是private,都是在头文件中定义的,没有办法做到公私分明。
libcamera关于Extensible/Private的设计模式,可以做到公私分明,很好地解决了这种问题。这里对这种设计模式做出一些介绍说明。
不过个人感觉,C++应该支持一个功能:把私有成员函数和成员变量写到cpp中,用private关键字说明,避免额外的设计。
Private和Extensible
class Private
class Private
{
public:
Private() { _o = nullptr; };
virtual ~Private();
template<typename T>
T *_o() { return static_cast<T *>(o_); }
private:
friend class Extensible;
Extensible *const o_;
};
这是一个保存私有成员的基类,它有以下特点:
- 它的成员为Extensible *const o_,表示可以从private -> public,通过_o返回
- Extensible类型的o_,是通过Extensible派生类的指针转化的
- 模板化T *_o()表示返回的其实是Extensible的派生类;这里也可以直接返回Extensible,但是需要用户每次手动转化为派生类(如Camera)
- 构造函数中初始化_o为nullptr,通过friend可以让class Extensible直接修改_o
- 虚析构函数表示析构时,先析构派生类,再析构基类;这点和构造相反
class Extensible
class Extensible
{
public:
Extensible(std::unique_ptr<Extensible::Private> d)
: d_(std::move(d))
{
*const_cast<Extensible **>(&d_->o_) = this;
}
protected:
template<typename T>
T *_d()
{
return static_cast<T *>(d_.get());
}
private:
const std::unique_ptr<Private> d_;
这是一个保存公共成员的基类,它有以下特点:
- 它的成员为unique_ptr
d_,表示可以从public -> private,通过_d返回 - d_是保存公共成员的基类,模板化表示返回的其实是Private的派生类,也就是Camera::Private
- 构造函数中,把this传给d_,与上面Private成员o_呼应,实现了public <--> private互访
Camera和Camera::Private1
class Camera::Private1
class Camera::Private1 : public Extensible::Private
{
friend class Camera;
...
}
先来看Private1,它有以下特点:
- 这里取名Private1,为了区分Extensible::Private,Camera的私有类可以叫任意名
- Camera继承了Extensible,Private1也要继承Private,这样Camera才可以借助Extensible/Private框架与Private1交互
class Camera
Class Camera: public Extensible
{
Private1 *_d() { return Extensible::_d<Private1>(); }
Camera(std::unique_ptr<Private1> d) : Extensible(std::move(d)) {}
}
Camera有以下特点:
- 继承自Extensible,说明Camera is a Extensible
- Camera将自己的私有类Private1传给Extensible,然后借助Extensible/Private框架与Private1交互
- 这里的_d()覆盖基类的_d(),_d()可以叫任意名称 —— 所谓的成员函数覆盖,都可以不覆盖,另起名调用
本文来自博客园,作者:moonのsun,转载请注明原文链接:https://www.cnblogs.com/moon-sun-blog/p/19396679

浙公网安备 33010602011771号