当前位置:网站首页>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.
边栏推荐
- "ArchSummit: The cry of the times, technical people can hear"
- The Principle Of Percona Toolkit Nibble Algorithm
- 请问shake数据库中为什么读取100个collection 后,直接就退出了,不继续读了呢?
- 风险策略调优中重要的三步分析法
- API设计笔记:pimpl技巧
- Typescript22 - interface inheritance
- EntityFramework saves to SQLServer decimal precision is lost
- Input输入框光标在前输入后自动跳到最后面的bug
- MLP neural network, GRNN neural network, SVM neural network and deep learning neural network compare and identify human health and non-health data
- typescript26-字面量类型
猜你喜欢
Valentine's Day Romantic 3D Photo Wall [with source code]
[Getting Started Tutorial] Rollup Module Packager Integration
Article summary: the basic model of VPN and business types
Passive anti-islanding-UVP/OVP and UFP/OFP passive anti-islanding model simulation based on simulink
High Numbers | 【Re-integration】Line Area Score 880 Examples
Simulation of Active anti-islanding-AFD Active Anti-islanding Model Based on Simulink
基于ProXmoX VE的虚拟化家庭服务器(篇一)—ProXmoX VE 安装及基础配置
Message queue design based on mysql
Software Testing Weekly (Issue 82): In fact, all those who are entangled in making choices already have the answer in their hearts, and consultation is just to get the choice that they prefer.
button去除黑框
随机推荐
Interview Blitz 69: Is TCP Reliable?Why?
Unknown Bounded Array
typescript22-接口继承
Message queue MySQL table for storing message data
[Getting Started Tutorial] Rollup Module Packager Integration
Typescript22 - interface inheritance
移动端页面秒开优化总结
Make your Lottie support word wrapping in text fields
风险策略调优中重要的三步分析法
数据比对功能调研总结
Immutable
最新 955 不加班的公司名单
Flink 1.13 (8) CDC
How to promote new products online?
button去除黑框
基于STM32设计的UNO卡牌游戏(双人、多人对战)
This article takes you to understand the past and present of Mimir, Grafana's latest open source project
智芯传感输液泵压力传感器 为精准智能控制注入科技“强心剂”
FFmpeg 搭建本地屏幕录制环境
What is dynamic programming and what is the knapsack problem