当前位置:网站首页>API Design Notes: The pimpl trick
API Design Notes: The pimpl trick
2022-08-01 04:26:00 【Pick up cues】
pimpl
pointer to implementation:指向实现的指针,Use this trick to avoid exposing private details in header files,可以促进APIInterface and implementation remain completely separate.
PimplA data member of a class can be defined as a pointer to a declared type,这里的类型仅仅作为名字引入,not fully defined,So we can hide the type definition in .cpp中,This is called an opaque pointer.
Below is an automatic timerAPI,Will print its lifetime when destroyed.
原有api
// autotimer.h
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/time.h>
#endif
#include <string>
class AutoTimer
{
public:
// Create new timers with easy-to-understand names
explicit AutoTimer(const std::string& name); // xplicitAvoid implicit construction, Only through display(explicit)构造.
// The timer reports the time-to-live on destruction
~AutoTimer();
private:
// Returns how long the object has been around
double GetElapsed() const;
std::string mName;
#ifdef _WIN32
DWORD mStartTime;
#else
struct timeval mStartTime;
#endif
};
这个APIThe design contains several disadvantages as follows:
1、Contains platform-specific definitions
2、Exposes the low-level details of how timers are stored on different platforms
3、Declare private members in public header files.(这是C++要求的)
The designer's real intention is to hide all private members.cpp文件中,这样我们可以使用Pimpl惯用法了.
Put all private members in an implementation class,这个类在头文件中前置声明,在.cpp中定义,下面是效果:
autotimer.h
// autotimer.h
#include <string.h>
class AutoTimer {
public:
explicit AutoTimer(const std::string& name);
~AutoTimer();
private:
class Impl;
Impl* mImpl;
};
Constructor requires allocationAutoTimer::Impltype variable and destroyed in the destructor.
All private members must passmImpl指针访问.
autotimer.cpp
// autotimer.cpp
#include "autotimer.h"
#include <iostream>
#if _WIN32
#include <windows.h>
#else
#include <sys/time.h>
#endif
class AutoTimer::Impl
{
public:
double GetElapsed() const
{
#ifdef _WIN32
return (GetTickCount() - mStartTime) / 1e3;
#else
struct timeval end_time;
gettimeofday(&end_time, NULL);
double t1 = mStartTime.tv_usec / 1e6 + mStartTime.tv_sec;
double t2 = end_time.tv_usec / 1e6 + end_time.tv_sec;
return t2 - t1;
#endif
}
std::string mName;
#ifdef _WIN32
DWORD mStartTime;
#else
struct timeval mStartTime;
#endif
};
AutoTimer::AutoTimer(const std::string& name) : mImpl(new AutoTimer::Impl())
{
mImpl->mName = name;
#ifdef _WIN32
mImpl->mStartTime = GetTickCount();
#else
gettimeofday(&mImpl->mStartTime, NULL);
#endif
}
AutoTimer::~AutoTimer()
{
std::cout << mImpl->mName << ":took" << mImpl->GetElapsed()
<< " secs" << std::endl;
delete mImpl;
mImpl = NULL;
}
ImplThe definition of contains all private methods and variables exposed in the original header file.
AutoTimer's constructor allocates a new oneAutoTimer::Implobject and initialize its members,The destructor is responsible for destroying the object.
Impl类为AutoTimer的私有内嵌类,如果想让.cppOther classes or free function access in the fileImplIf so, it can be declared as a public class.
// autotimer.h
#include <string.h>
class AutoTimer {
public:
explicit AutoTimer(const std::string& name);
~AutoTimer();
class Impl;
private:
Impl* mImpl;
};
如何规划Impl类中的逻辑?
Generally place all private members and private methods in Impl类中,You can avoid declaring private methods in public header files.
注意事项:
不能在ImplHide private virtual functions in the class,Virtual functions must appear in public classes,This ensures that any derived class can override them
pimpl的复制语义
在c++中,If no copy constructor and assignment operator are explicitly defined for the class,C++The compiler will create it by default,But this default function can only perform a shallow copy of the object,This is not good for classes that have pointer members in the class.
If the client copied the object,Then the two object pointers will point to the same oneImpl对象,Two objects may try to delete the same object twice in the destructor resulting in a crash.
Two solutions are provided below:
1、禁止复制类,Objects can be declared non-copyable
2、Explicitly define copy semantics
#include <string>
class AutoTimer
{
public:
explicit AutoTimer(const std::string& name);
~AutoTimer();
private:
AutoTimer(const AutoTimer&);
const AutoTimer &operator=(const AutoTimer&);
class Impl;
Impl* mImpl;
}
Smart pointer optimizationPimpl
Optimize object deletion with the help of smart pointers,Shared pointers are used hereor作用域指针.Since scope pointers are defined as not copyable,So using it directly also saves the code for declaring private copy constructs and operators.
#include <string>
class AutoTimer
{
public:
explicit AutoTimer(const std::string& name);
~AutoTimer();
private:
class Impl;
boost::scoped_ptr<Impl> mImpl;
// 如果使用shared_ptrYou need to write your own copy constructs and operators
}
Pimpl优缺点总结
优点:
1、信息隐藏
2、降低耦合
3、加速编译:Implement file move in.cpp降低了apicitation hierarchy,Directly affects compile time
4、二进制兼容性:Any modification to member variables is forPimplThe size of the object pointer is always the same
5、惰性分配:mImplClasses can be restructured when needed
缺点:
1、增加了ImplClass allocation and deallocation,May introduce performance conflicts.
2、Accessing all private members requires a layer outsidemImpl→,This complicates the code.
边栏推荐
- 请问shake数据库中为什么读取100个collection 后,直接就退出了,不继续读了呢?
- PMP 项目沟通管理
- scheduleWithFixedDelay和scheduleAtFixedRate的区别
- 数组问题之《两数之和》以及《三数之和 》
- TypeScript simplifies running ts-node
- Dart named parameter syntax
- Elastic Stack的介绍
- Message queue MySQL table for storing message data
- Valentine's Day Romantic 3D Photo Wall [with source code]
- Progressive Reconstruction of Visual Structure for Image Inpainting 论文笔记
猜你喜欢
随机推荐
Dart 命名参数语法
Unknown Bounded Array
PMP 相关方管理必背总结
7月编程排行榜来啦!这次有何新变化?
RSA主要攻击方法
Hackers can how bad to what degree?
6-23漏洞利用-postgresql代码执行利用
EntityFramework saves to SQLServer decimal precision is lost
Immutable
产品经理访谈 | 第五代验证码的创新与背景
Progressive Reconstruction of Visual Structure for Image Inpainting 论文笔记
Visual Studio提供的 Command Prompt 到底有啥用
PMP 80个输入输出总结
雪糕和轮胎
故乡的素描画
软件测试面试(三)
MySQL4
在沈自所的半年总结
【云原生之kubernetes实战】kubernetes集群的检测工具——popeye
This article takes you to understand the past and present of Mimir, Grafana's latest open source project