问题标签 [pimpl-idiom]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
604 浏览

c++ - 与类成员变量一起使用的 Pimpl 习惯用法

实现这个类的正确方法是什么?

0 投票
4 回答
227 浏览

c++ - 从枚举定义中删除依赖常量

我试图通过使用不透明的结构和前向声明从我的项目中安全地删除依赖项,但像大多数人一样,我仍然停留在我的枚举上。

我试图从头文件中删除的头文件依赖项定义了我想将枚举值设置为的常量。像这样的东西

我试图找出一种不必在我的标题中包含依赖标题的方法。

答案很可能只是“你不能那样做”,但我只是想问一下,因为一个解决方案会让我的生活无限轻松。

0 投票
2 回答
2233 浏览

c++ - 用最少的代码实现 pImpl

可以使用什么样的技巧来最小化实现 pImpl 类的工作量?

标题:

执行:

您将如何改进这一点,使用 Boost、可能的继承、CRTP 或其他技巧来避免尽可能多的样板代码?运行时性能不是问题。

0 投票
5 回答
4468 浏览

c++ - pImpl 习语和可测试性

c++ 中的 pImpl 习惯用法旨在向该类的用户隐藏该类的实现细节(=私有成员)。然而,它也隐藏了该类的一些依赖关系,从测试的角度来看,这些依赖关系通常被认为是不好的。

例如,如果 A 类将其实现细节隐藏在只能从 A.cpp 访问的 AImpl 类中,并且 AImpl 依赖于许多其他类,那么对 A 类进行单元测试就变得非常困难,因为测试框架无法访问AImpl 也没有办法将依赖项注入到 AImpl 中。

有没有人遇到过这个问题?你找到解决方案了吗?

- 编辑 -

在相关主题上,似乎人们建议只测试接口公开的公共方法,而不是内部方法。虽然我可以从概念上理解该陈述,但我经常发现我需要单独测试私有方法。例如,当公共方法调用包含一些非平凡逻辑的私有帮助方法时。

0 投票
5 回答
1955 浏览

c++ - C++ pimpl idiom 浪费了一条指令与 C 风格?

是的,我知道一条机器指令通常无关紧要。我问这个问题是因为我想了解 pimpl 成语,并以最好的方式使用它;而且有时我确实关心一条机器指令。 )

在下面的示例代码中,有两个类,ThingOtherThing. 用户将包括“thing.hh”。 Thing使用 pimpl 习惯用法来隐藏它的实现。 OtherThing使用 C 风格——返回和获取指针的非成员函数。这种风格会产生更好的机器代码。我想知道:有没有办法使用 C++ 风格——即将函数变成成员函数——但仍然保存机器指令。我喜欢这种风格,因为它不会污染类外的命名空间。

注意:我只关注调用成员函数(在本例中为calc)。我不是在看对象分配。

以下是我 Mac 上的文件、命令和机器代码。

事情.hh:

东西.cc:

main.cc (只是为了测试代码实际工作......)

生成文件:

运行make,然后查看机器代码。在我使用的 mac 上otool -tv thing.o | c++filt。在 linux 上,我认为是objdump -d thing.o. 这是相关的输出:

物质:: calc():
0000000000000000 MOVQ(%rdi),%RAX
0000000000000003 MOVL(%RAX),%EAX 00000000000000000005 含量
含量
000000000000000000000007 ret
calc(earthting*) 0000000000000014 ret


由于指针间接,请注意额外的指令。第一个函数查找两个字段(impl,然后是 x),而第二个函数只需要获取 x。可以做什么?

0 投票
3 回答
429 浏览

c++ - 委派到私人领域

有时,C++ 的隐私概念让我感到困惑 :-)

既然Foo::Bar是,private我不能申报b。但是我可以很好main地调用方法。Foo::Bar为什么这是允许的?这是意外还是设计使然?


哦,等等,它变得更好了:

即使我不允许命名类型Foo::Bar,它也适用于auto...


诺亚写道:

在类定义中定义的类型名称不能在没有限定的情况下在其类之外使用。

只是为了好玩,以下是从外部获取类型的方法:

0 投票
2 回答
1619 浏览

c++ - 将私有部分保留在 C++ 头文件之外:纯虚拟基类 vs pimpl

我最近从 Java 和 Ruby 切换回 C++,令我惊讶的是,当我更改私有方法的方法签名时,我必须重新编译使用公共接口的文件,因为私有部分也在 .h 文件中。

我很快想出了一个解决方案,我猜这是 Java 程序员的典型解决方案:接口(= 纯虚拟基类)。例如:

香蕉树.h:

香蕉树.cpp:

这里唯一的麻烦是我不能使用new,而必须调用BananaTree::create(). 我不认为这真的是一个问题,特别是因为我预计无论如何都会大量使用工厂。

然而,现在,C++ 成名的智者提出了另一种解决方案,即pImpl idiom。这样,如果我理解正确,我的代码将如下所示:

香蕉树.h:

香蕉树.cpp:

这意味着我必须为 的每个公共方法实现装饰器风格的转发方法BananaTree,在这种情况下getBanana。这听起来像是增加了我不想要求的复杂性和维护工作。

那么,现在的问题是:纯虚拟类方法有什么问题?为什么 pImpl 方法的文档记录得这么好?我错过了什么吗?

0 投票
3 回答
1613 浏览

c++ - 这是使用 PIMPL 模式的好地方吗?

我正在开发一个为某些服务定义客户端接口的库。在后台,我必须验证用户提供的数据,然后使用来自另一个库的 Connection 类将其传递给“引擎”进程(注意:我们库的用户不知道 Connection 类)。我的一位同事建议使用 PIMPL:

但是,我发现很难测试——即使我将测试链接到 Connection 的一些模拟实现,我也无法轻松访问它来设置和验证期望。我是否遗漏了什么,或者更清洁和可测试的解决方案是使用接口 + 工厂:

在这种情况下是否有任何理由选择 PIMPL?

0 投票
2 回答
1544 浏览

c++ - PIMPL 和堆栈分配

所以我一直在考虑 PIMPL 和堆栈分配。我一直在编写一个库,并决定使用 PIMPL 来隐藏该类的私有成员。这意味着我会有一个像这样声明的类

这很简单。但是然后在构造函数中你这样做

因此,当有人使用我的库在堆栈上创建 Foo 时,他们本质上是在进行堆分配。这是您在使用 PIMPL 时必须接受的权衡吗?我想在构造函数旁边发布带有警告的文档:“警告:这会导致堆分配”或类似的东西。

我的另一个想法是让所有暴露给实现的类作为纯虚拟接口和一大堆返回智能指针的静态工厂方法。这也意味着堆分配,但没有任何技巧。

有什么想法或建议吗?我是否过分考虑使用我的库的程序员?

0 投票
7 回答
2597 浏览

c++ - pimpl 习惯用法如何减少依赖关系?

考虑以下:

PImpl.hpp

PImpl.cpp

实现.hpp

客户端.cpp

这种模式背后的想法是,它Impl的接口可以改变,但客户端不必重新编译。然而,我看不出这是怎么回事。假设我想为这个类添加一个方法——客户端仍然需要重新编译。

基本上,我能看到的唯一需要更改类的头文件的更改是类的接口发生更改的事情。当这种情况发生时,无论是 pimpl 还是没有 pimpl,客户端都必须重新编译。

在不重新编译客户端代码方面,这里的哪些类型的编辑给我们带来了好处?