C++ pimpl机制详细讲解

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日

相关文章

  • asp生成不需要数据库的中奖码

    对于“asp生成不需要数据库的中奖码”的问题,我将提供完整的攻略。 首先,我们需要定义一个用来生成中奖码的函数。这个函数需要满足以下要求: 需要生成固定长度的中奖码。 每个中奖码由字母和数字组成。 中奖码不能重复。 下面是一个示例代码,用于生成6位长度的中奖码: Function GenerateCode() Dim code Dim i Randomize…

    C 2023年5月23日
    00
  • C++ boost::asio编程-同步TCP详解及实例代码

    C++ boost::asio编程-同步TCP详解及实例代码 简介 本文将详细讲解使用C++ boost::asio库进行同步TCP编程的方式,并提供两个实例代码进行说明。 什么是boost::asio boost::asio是一个使用纯C++编写的网络编程库,它提供了简化网络编程的接口,并且支持多种协议。boost::asio的设计中注重运行时效率和可靠性…

    C 2023年5月23日
    00
  • C语言中递增和递减运算符的区别

    下面详细讲解C语言中递增和递减运算符的区别。 什么是递增和递减运算符 在C语言中,递增运算符++和递减运算符–分别可以将变量的值增加或者减少1。它们可以作用于整型、浮点型、字符型等基本数据类型的变量。 递增和递减运算符可以在变量前面或者后面使用,使用的方式决定了它们的执行顺序,也影响了最终计算出的结果。 前置和后置运算符的区别 递增和递减运算符可以前置(放…

    C 2023年5月10日
    00
  • C语言如何与ARM汇编语言混合编程示例详解

    下面是针对”C语言如何与ARM汇编语言混合编程”的完整攻略,并附上两个示例说明: 1. 混合编程概述 C语言是一种高级编程语言,开发者使用它编写程序时可以更加关注问题的实现和算法的设计。而汇编语言则是底层的计算机指令语言,可直接使用计算机的基础架构来控制程序的运行。混合编程即是将C语言和汇编语言结合起来使用,利用C语言的高级特性和汇编语言的底层特性,有效地优…

    C 2023年5月23日
    00
  • C++中的String的常用函数用法(最新推荐)

    下面是关于C++中的String的常用函数用法的完整攻略: 1. String的基础用法 在C++中使用String需要引入头文件,并且使用std::命名空间来定义,下面是一个String的基本使用范例: #include <iostream> #include <string> int main() { std::string st…

    C 2023年5月23日
    00
  • 电脑出现错误代码0xc000012f提示的解决方法图文教程

    电脑出现错误代码0xc000012f提示的解决方法图文教程 当我们使用电脑时,经常会出现各种各样的错误提示。其中错误代码0xc000012f是比较常见的。在本次教程中,我们将详细讲解这个问题的解决方法,包括图文示例。 问题描述 当出现错误代码0xc000012f时,通常会伴随着以下错误提示: 无法加载 %hs,因为找不到或无法加载所需的文件。此应用程序无法继…

    C 2023年5月23日
    00
  • C语言实现2D赛车游戏的示例代码

    下面我将详细讲解如何实现一个简单的2D赛车游戏。 1. 实现思路 首先,我们需要了解游戏的基本组成部分: 游戏场景 赛车模型 道路模型 背景音乐 操作控制 根据以上组成部分,我们可以总体将实现思路分为以下几个步骤: 创建画布:使用某种绘图库创建基础画布,用于绘制游戏场景。 绘制游戏场景:在基础画布上绘制游戏所需的场景元素,包括道路和赛车模型。 添加背景音乐:…

    C 2023年5月23日
    00
  • ACProtect Professional 1.3C 主程序脱壳(1)(图)

    ACProtect Professional 1.3C 主程序脱壳攻略 1. 准备环境 系统环境:Windows操作系统(建议Windows 7以上) 调试器:OllyDbg、x64dbg或者IDA Pro HEX编辑器:WinHex等工具 脱壳工具:ACProtect Unpacker等 2. 破解过程 2.1 加载目标程序并分析 将ACProtect P…

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