C++ pimpl机制详细讲解

yizhihongxing

C++ pimpl机制详细讲解

什么是pimpl机制

pimpl,即Private Implementation(私有实现),也叫Opaque Pointer(不透明指针),是一种C++编程技巧/设计模式,它的本质是把类的实现(类的成员变量和方法)隐藏到源文件中,只把类的接口(类的公有成员函数)暴露出去。

pimpl机制的优缺点

优点:

  • 隐藏了类的实现细节,可以防止其他程序员干预我们的内部实现。

  • 由于所有实现在cpp文件中,可以避免一些头文件常见的循环依赖的问题。

缺点:

  • 在每个类中都需要写一个指向实现类的指针,会增加代码量和复杂度。

  • 在使用pimpl的类中始终存在指针解引用所带来的额外开销。

pimpl机制的使用方法

1.在头文件中定义一个只有前向声明的类。

//test.h

class Test
{
public:
    Test();
    ~Test();
    void test();
private:
    class Impl;
    Impl* pImpl;   
};

2.ccp文件中定义类的实现。

//test.cpp

class Test::Impl
{
public:
    void doTest();
    ~Impl(){ std::cout << "~Impl" << std::endl; }
};

Test::Test()
    :pImpl(new Impl)
{
    std::cout << "Test" << std::endl;
}

Test::~Test()
{
    delete pImpl;
    std::cout << "~Test" << std::endl;
}

void Test::test()
{
    pImpl->doTest();
}

void Test::Impl::doTest()
{
    std::cout << "doTest" << std::endl;
}

3.在使用类的地方,只需要包含头文件即可。

//main.cpp

#include <iostream>
#include "test.h"

int main()
{
    Test test;
    test.test();
    return 0;
}

pimpl机制的示例

示例1:使用pimpl机制实现简单的字符串类

具体实现如下:

#include <string>

class String
{
public:
    String();    
    String(const char* str);
    String& operator=(const String& other);
    String(const String& str);
    ~String();
    void print() const;
private:
    class StringImpl;
    StringImpl* pImpl;    
};

class String::StringImpl
{
public:
    StringImpl();
    StringImpl(const char* str);
    ~StringImpl();
    std::string str;    
};

String::String()
    :pImpl(new StringImpl)
{}

String::String(const char* str)
    : pImpl(new StringImpl(str))
{}

String::String(const String& str)
    :pImpl(new StringImpl(str.pImpl->str))
{}

String& String::operator=(const String& other)
{
    if (pImpl == other.pImpl)
        return *this;
    StringImpl* tmp = pImpl;
    pImpl = new StringImpl(other.pImpl->str);
    delete tmp;
    return *this;    
}

String::~String()
{
    delete pImpl;
}

void String::print() const
{
    std::cout << pImpl->str << std::endl;
}

String::StringImpl::StringImpl()
{}

String::StringImpl::StringImpl(const char* str)
    :str(str)
{}

String::StringImpl::~StringImpl()
{}

int main()
{
    String str1("hello");
    String str2 = str1;
    str1.print();
    str2.print();
    String str3;
    str3 = str2;
    str3.print();
    return 0;
}

以上示例代码中,String类的数据成员都放在了StringImpl类中。

示例2:使用pimpl机制实现图形类

具体实现如下:

class Shape
{
public:
    virtual void draw() = 0;
    virtual ~Shape() {}
};

class Rectangle : public Shape
{
public:
    void draw() { std::cout << "draw rectangle" << std::endl; }
};

class Circle : public Shape
{
public:
    void draw() { std::cout << "draw circle" << std::endl; }
};

class ShapeFacade
{
public:
    ShapeFacade(Shape* shape);
    void draw();
    ~ShapeFacade();
private:
    Shape* pShape;
};

class ShapeFacade::Impl
{
public:
    ShapeFacade::Impl(Shape* shape)
        : pShape(shape)
    {}
    void draw()
    {
        pShape->draw();
    }
private:
    Shape* pShape;
};

ShapeFacade::ShapeFacade(Shape* shape)
    :pImpl(new ShapeFacade::Impl(shape))
{}

ShapeFacade::~ShapeFacade()
{
    delete pImpl;
}

void ShapeFacade::draw()
{
    pImpl->draw();
}

int main()
{
    ShapeFacade rect(new Rectangle);
    rect.draw();
    ShapeFacade circle(new Circle);
    circle.draw();
    return 0;
}

以上示例代码中,Shape类是一个纯虚基类,用于定义图形类的接口。Rectangle和Circle类是Shape的具体实现。ShapeFacade类是一个门面类,用于给外部程序呈现简洁的接口,它的实现被隐藏在Impl类中。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++ pimpl机制详细讲解 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • C++嵌入式内存管理详情

    关于C++嵌入式内存管理,以下是完整的攻略: C++嵌入式内存管理概述 在嵌入式系统开发中,动态内存的使用是非常受限的,因此需要采用静态内存管理或者是内存池来代替动态内存分配。C++ 的运行时库也支持内存池技术,可以用于嵌入式系统开发中。 C++ 的内存池管理主要依赖于 new 和 delete 运算符来实现,通过重载 new 和 delete 运算符来达到…

    C 2023年5月23日
    00
  • python中的Json模块dumps、dump、loads、load函数用法详解

    下面是关于 Python 中的 Json 模块 dumps、dump、loads、load 函数的使用详解: Json 简介 Json是一种基于文本的轻量级数据交换格式,常用于前后端数据交互、配置文件等场合。在 Python 中,可以使用 Json 模块来对 Json 数据进行解析和生成。 Json 模块函数说明 dumps 函数 dumps 函数将一个 P…

    C 2023年5月23日
    00
  • C语言实现简单职工信息管理系统

    C语言实现简单职工信息管理系统 1. 系统功能 本职工信息管理系统主要实现以下功能: 添加职工 显示职工信息 删除职工 修改职工信息 查找职工信息 排序职工信息 清空职工信息 退出系统 2. 系统设计 本系统主要由以下几个部分组成: 职工结构体定义 菜单函数实现 添加职工函数实现 显示职工信息函数实现 删除职工函数实现 修改职工信息函数实现 查找职工信息函数…

    C 2023年5月24日
    00
  • C 程序 对字符串集排序

    下面是详细讲解“C 程序 对字符串集排序”的完整使用攻略。 概述 在 C 语言中,我们可以使用 qsort() 函数对字符串集进行排序。具体来说,我们需要填写几个参数,包括要排序的字符串数组指针、字符串数组中字符串的个数、每个字符串的长度、和一个比较函数指针。比较函数指针是用来告诉 qsort() 函数如何进行排序的,这个函数会比较两个字符串,然后返回一个负…

    C 2023年5月9日
    00
  • Java深入讲解异常处理try catch的使用

    Java深入讲解异常处理try catch的使用 在Java中,异常处理是非常重要的一部分。通过异常处理,我们可以及时发现并解决程序中的错误,保证程序的正常运行。其中,try catch语句是最常用的异常处理方式之一。本文将详细讲解Java中异常处理try catch的使用,帮助读者更好地理解和掌握异常处理的方法。 try catch语句的基本用法 Java…

    C 2023年5月23日
    00
  • 代码讲解C++继承和派生

    这里我就来详细讲解一下“代码讲解C++继承和派生”的完整攻略。 1. C++继承 C++中的继承是指从一个类中派生出另一个类,具体实现方式为在派生类的定义中使用“:”后面跟上基类的名称。 1.1 基类和派生类的定义 下面是一个基类的定义: class Shape { public: virtual void draw() = 0; virtual doubl…

    C 2023年5月24日
    00
  • 从零学习构造系统之bazel示例详解

    从零学习构造系统之bazel示例详解 简介 本文将详细讲解使用bazel构建系统的过程。Bazel是由Google开发的构建工具,其目的是为了更快、更可靠地构建软件。Bazel不仅支持多种语言的构建,如Java、C++、Python等等,而且具有增量构建和缓存等强大的功能。 安装Bazel 首先,我们需要安装Bazel。可以在Bazel的官方网站(https…

    C 2023年5月23日
    00
  • C++11实现简易定时器的示例代码

    下面是关于“C++11实现简易定时器的示例代码”的完整攻略。 标题 C++11实现简易定时器的示例代码 简介 在开发事件驱动或多线程程序时,经常需要一种定时器来控制任务的执行时间。本篇攻略将介绍如何使用C++11编写一个简易的定时器,以此来满足我们在各种场景中的需求。 本攻略将包含两个实例展示如何使用简易定时器,读者可以通过这两个实例学习如何将其应用于自己的…

    C 2023年5月22日
    00
合作推广
合作推广
分享本页
返回顶部