对头文件进行更改时,包括它的所有源都需要重新编译。在大型项目和库中,由于即使对实现进行了很小的更改,每个人都必须等待一段时间才能编译代码,这可能会导致构建时间问题。解决此问题的一种方法是使用PImpl Idiom ,它将实现隐藏在标头中,并包括一个可立即编译的接口文件。
PImpl成语(实现的指针)是一种用于将实现与接口分离的技术。它通过将私有数据成员移到单独的类中并通过不透明指针访问它们,最大程度地减少了标头暴露,并帮助程序员减少了构建依赖性。
实施方法:
- 创建一个单独的类(或struct)以实现
- 将所有私有成员从头到该类。
- 在头文件中定义一个实现类(Impl)。
- 在头文件中,创建指向实现类的前向声明(指针) 。
- 定义一个析构函数和一个复制/赋值运算符。
显式声明析构函数的原因是,在编译时,智能指针( std :: unique_ptr )检查类型定义中是否存在可见的析构函数,如果仅向前声明,则会引发编译错误。
使用智能指针是一种更好的方法,因为指针可以控制PImpl的生命周期。
例子:
Header file
/* |INTERFACE| User.h file */
#pragma once
#include // PImpl
#include
using namespace std;
class User {
public:
// Constructor and Destructors
~User();
User(string name);
// Asssignment Operator and Copy Constructor
User(const User& other);
User& operator=(User rhs);
// Getter
int getSalary();
// Setter
void setSalary(int);
private:
// Internal implementation class
class Impl;
// Pointer to the internal implementation
unique_ptr pimpl;
};
Implementation file
/* |IMPLEMENTATION| User.cpp file */
#include "User.h"
#include
using namespace std;
struct User::Impl {
Impl(string name)
: name(name){};
~Impl();
void welcomeMessage()
{
cout << "Welcome, "
<< name << endl;
}
string name;
int salary = -1;
};
// Constructor connected with our Impl structure
User::User(string name)
: pimpl(new Impl(name))
{
pimpl->welcomeMessage();
}
// Default Constructor
User::~User() = default;
// Assignment operator and Copy constructor
User::User(const User& other)
: pimpl(new Impl(*other.pimpl))
{
}
User& User::operator=(User rhs)
{
swap(pimpl, rhs.pimpl);
return *this;
}
// Getter and setter
int User::getSalary()
{
return pimpl->salary;
}
void User::setSalary(int salary)
{
pimpl->salary = salary;
cout << "Salary set to "
<< salary << endl;
}
PImpl的优点:
- 二进制兼容性:二进制接口独立于私有字段。对实现进行更改不会使相关代码停滞不前。
- 编译时间:由于只需要重建实现文件而不是每个客户端都重新编译其文件,因此编译时间减少了。
- 数据隐藏:可以轻松隐藏某些内部细节,例如实现技术和用于实现公共接口的其他库。
PImpl的缺点:
- 内存管理:由于分配的内存多于默认结构,因此内存使用量可能增加,这对于嵌入式软件开发至关重要。
- 维护工作:由于为了使用pimpl和附加的指针间接调用而增加了类,因此维护变得更加复杂(只能通过指针/引用使用接口) 。
- 继承:尽管类PImpl可以继承隐藏的实现。
参考: https : //en.cppreference.com/w/cpp/language/pimpl
要从最佳影片策划和实践问题去学习,检查了C++基础课程为基础,以先进的C++和C++ STL课程基础加上STL。要完成从学习语言到DS Algo等的更多准备工作,请参阅“完整面试准备课程” 。