前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Example】C++ 用于编译时封装的 Pimpl 演示 (编译防火墙 Private-IMPL)

【Example】C++ 用于编译时封装的 Pimpl 演示 (编译防火墙 Private-IMPL)

原创
作者头像
芯片烤电池
修改2022-04-28 10:07:02
5750
修改2022-04-28 10:07:02
举报
文章被收录于专栏:C++教程

什么是  Private-IMPL ?

即【隐藏实现的方式】,如果你还停留在学习的阶段,那这种方式对你的代码几乎毫无用处。

但是如果你走入到真实项目当中,这种方式又显得尤为重要。

微软对 Private-IMPL 模式的简单概述(现代C++) 

为什么:

1,它可以对外人尽可能隐藏你类内部实现,因为你的 dll 要给别人用,总要提供头文件,对吧?

2,它可以尽可能减少头文件的 include 次数。

3,它可以尽可能减轻编译依赖,从而提高编译速度。

4,接口与实现分离的概念。

5,提高代码可移植性,接口专注当前项目业务,实现则专注于算法。如果需要复用代码,直接Copy走实现类改名重写接口就可以了。

那什么时候不能使用呢?

1,如果你的类本身非常简单,比如说职责就是共享个数据,就不要使用这种模式,函数的过度嵌套调用会大量消耗栈内存。

2,继承了更深层次的基类,这时你的子类应该专注于业务,将高度复用的代码写入基类,而不是进一步将子类复杂化。

那么  Private-IMPL 的具体实现方式是?

在类内部创建一个私有子类,将函数功能的具体实现写入到私有子类当中,类本身的函数只当做接口专注于业务交互。

演示代码:

================== 创建一个叫大脑工具箱的“工具类” ==================

----------------- 头文件 ----------------- 

代码语言:javascript
复制
#pragma once
#include <memory>
#include <vector>

// 假设这是一个工具类
class BrainToolBox
{
public:
    // 构造和析构函数
    BrainToolBox();
    ~BrainToolBox();

    // 接口

    // 比方说...对一个vector进行冒泡排序(无聊)
    void SortVector(std::vector<int> &input);

    // 比方说...找到一个vector当中的最大值(更无聊)
    int GetVectorMaxValue(std::vector<int>& input);

// 私有化实现类
private:

    // 声明实现类
    class PrivateIMPL;

    // 实现类的指针
    std::unique_ptr<PrivateIMPL> _u;

};

我们已经在类定义头文件中将私有子类声明并且使用智能指针进行包装。

-----------------  CPP 文件 ----------------- 

在构造函数执行时,就要创建子类(实现类)的实例,这时必须要有实现类的定义,接着往下看。

代码语言:javascript
复制
#include "BrainToolBoxIMPL.h"

// 在构造函数执行时 同时构造实现类
BrainToolBox::BrainToolBox(): _u(new BrainToolBox::PrivateIMPL)
{

}

// 毫无存在感的析构 假设不使用智能指针方式 务必在析构中释放实现类的裸指针
BrainToolBox::~BrainToolBox()
{
    // 假设为裸指针
    // delete _u;
}

// 接口函数 对一个Vector进行冒泡的接口
void BrainToolBox::SortVector(std::vector<int> &input)
{
    // 调用实现函数
    _u->BubbleSortVector(input);

    // 假设在实际开发当中 需要将排序结果传出去 这里就可以进行传递操作
    // zmq_send(socket, vec, len, ZMQ_SNDMORE);
    return;
}

// 接口函数 找到一个Vector的最大值
int BrainToolBox::GetVectorMaxValue(std::vector<int>& input)
{
    // 调用实现函数
    return _u->SearchVectorMaxValue(input);
}

================== 创建大脑工具箱的实现类 ==================

----------------- 头文件 ----------------- 

我们在外部类当中仅仅是将实现类声明,这时就需要进行定义。

代码语言:javascript
复制
#pragma once
#include "BrainToolBox.h"

#include <algorithm>

// 定义BrainToolBox的实现类
class BrainToolBox::PrivateIMPL
{
public:
    // 对 Vector 进行冒泡排序的实现函数
    void BubbleSortVector(std::vector<int> &vec);

    // 找到一个 Vector 当中的最大值实现函数
    int SearchVectorMaxValue(std::vector<int>& vec);

};

-----------------  CPP 文件 ----------------- 

将函数的实现代码封装进实现类。

代码语言:javascript
复制
#include "BrainToolBoxIMPL.h"

// 实现一个冒泡排序
void BrainToolBox::PrivateIMPL::BubbleSortVector(std::vector<int>& vec)
{
    int vec_size = vec.size();
    for (size_t i = 0; i < vec_size; i++)
    {
        int trend_size = vec_size - i - 1;
        for (size_t j = 0; j < trend_size; j++)
        {
            if (vec[j] > vec[j + 1])
            {
                int k = vec[j];
                vec[j] = vec[j + 1];
                vec[j + 1] = k;
            }
        }
    }

    return;
}

// 实现返回vector最大值
int BrainToolBox::PrivateIMPL::SearchVectorMaxValue(std::vector<int>& vec)
{
    auto max_item = std::max_element(vec.begin(), vec.end());
    return *max_item;
}

================== 测试一下 ==================

代码语言:javascript
复制
#include <iostream>

#include <memory>
using std::shared_ptr;

#include <vector>
using std::vector;

#include "BrainToolBox.h"

int main()
{
    std::cout << "Hello Byte!" << std::endl;
    vector<int> values = {8, 5, 6, 1, 2, 7, 9, 3, 4, 10, 99, 50};
    
    shared_ptr<BrainToolBox> brain = shared_ptr<BrainToolBox>(new BrainToolBox);
    std::cout << "Vector最大值: " << brain->GetVectorMaxValue(values) << std::endl;

    brain->SortVector(values);
    std::cout << "排序后的Vector:" << std::endl;
    for (auto &item : values)
    {
        std::cout << item << " ";
    }

    return EXIT_SUCCESS;
}


====================================

芯片烤电池 C++ Example 2022-Spring Season Pass :

【Example】C++ 标准库常用容器全面概述

【Example】C++ 回调函数及 std::function 与 std::bind

【Example】C++ 运算符重载

【Example】C++ 标准库智能指针 unique_ptr 与 shared_ptr

【Example】C++ 接口(抽象类)概念讲解及例子演示

【Example】C++ 虚基类与虚继承 (菱形继承问题)

【Example】C++ Template (模板)概念讲解及编译避坑

【Example】C++ 标准库 std::thread 与 std::mutex

【Example】C++ 标准库多线程同步及数据共享 (std::future 与 std::promise)

【Example】C++ 标准库 std::condition_variable

【Example】C++ 用于编译时封装的 Pimpl 演示 (编译防火墙 Private-IMPL)

【Example】C++ 单例模式 演示代码 (被动模式、兼容VS2022编译)

====================================

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档