标签: pimpl-idiom

pimpl成语如何减少依赖?

考虑以下:

PImpl.hpp

class Impl;

class PImpl
{
    Impl* pimpl;
    PImpl() : pimpl(new Impl) { }
    ~PImpl() { delete pimpl; }
    void DoSomething();
};
Run Code Online (Sandbox Code Playgroud)

PImpl.cpp

#include "PImpl.hpp"
#include "Impl.hpp"

void PImpl::DoSomething() { pimpl->DoSomething(); }
Run Code Online (Sandbox Code Playgroud)

Impl.hpp

class Impl
{
    int data;
public:
    void DoSomething() {}
}
Run Code Online (Sandbox Code Playgroud)

client.cpp

#include "Pimpl.hpp"

int main()
{
    PImpl unitUnderTest;
    unitUnderTest.DoSomething();
}
Run Code Online (Sandbox Code Playgroud)

这种模式背后的想法是,Impl界面可以改变,但客户端不必重新编译.然而,我没有看到这是如何真实的情况.假设我想在这个类中添加一个方法 - 客户端仍然需要重新编译.

基本上,只有种这样的,我可以看到的变化不断需要改变头文件一类的东西,其中的类发生变化的接口.当发生这种情况时,pimpl或没有pimpl,客户端必须重新编译.

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

c++ pimpl-idiom

8
推荐指数
3
解决办法
2213
查看次数

Pimpl + QSharedPointer - 析构函数=灾难

昨天我遇到了痛苦,让我感到沮丧24小时.问题归结为随机发生的意外崩溃.更复杂的是,调试报告也具有绝对随机的模式.更复杂的是,所有调试跟踪都会导致随机 Qt源或本机DLL,即证明每次问题都不在我身边.

这里有几个这样可爱的报告的例子:

Program received signal SIGSEGV, Segmentation fault.
0x0000000077864324 in ntdll!RtlAppendStringToString () from C:\Windows\system32\ntdll.dll
(gdb) bt
#0 0x0000000077864324 in ntdll!RtlAppendStringToString () from C:\Windows\system32\ntdll.dll
#1 0x000000002efc0230 in ?? ()
#2 0x0000000002070005 in ?? ()
#3 0x000000002efc0000 in ?? ()
#4 0x000000007787969f in ntdll!RtlIsValidHandle () from C:\Windows\system32\ntdll.dll
#5 0x0000000000000000 in ?? ()
Run Code Online (Sandbox Code Playgroud)
warning: HEAP: Free Heap block 307e5950 modified at 307e59c0 after it was freed
Program received signal SIGTRAP, Trace/breakpoint trap.
0x00000000778bf0b2 in ntdll!ExpInterlockedPopEntrySListFault16 () from …
Run Code Online (Sandbox Code Playgroud)

c++ qt destructor pimpl-idiom qsharedpointer

8
推荐指数
1
解决办法
1772
查看次数

在调试器中查看DLL中的pimpl

我正在使用pimpl成语来隐藏接口的实现细节,以便我可以有一些ABI保护措施.我不是那么精通MS的细节......在我的大部分开发生涯中使用Linux.

我无法从调试器检查窗口查看pimpl的内部.我的类型只扩展到impl的原始指针(它使用智能指针).我已经尝试导出符号,但这似乎不起作用.我想我实际上想要查看的符号没有被导入或者其他东西.

我该如何解决这个问题?可视化器可能会调用函数吗?

编辑 - 也许我把人们与出口事物混为一谈.

我正在尝试这个:

object.h:

struct EXPORT object {
    struct EXPORT impl;
    impl * pimpl;
};
Run Code Online (Sandbox Code Playgroud)

object.cpp

struct EXPORT object::impl {
    char member;
};
Run Code Online (Sandbox Code Playgroud)

我能想到解决问题的唯一方法是将impls放在包含在库的调试版本中的头文件中.希望有更好的解决方案.

c++ dll pimpl-idiom visual-studio-2010

8
推荐指数
1
解决办法
568
查看次数

使用PIMPL习语时有没有办法限制重复的样板?

我有以下内容:

// foo.h:
class foo {
public:
    foo(); 
    ~foo();
    // note: the param type repetition here is only incidental, assume the
    // functions can't easily be made to share type signatures
    void bar(a b, c d);               
    void baz(a b, c d, e f, g h, i j);
    void quux(a b, c d, e f, g h, i j);
private:
    class impl;
    impl *m_pimpl;
}
Run Code Online (Sandbox Code Playgroud)

然后:

// foo.cpp:
class foo::impl {
public:
    void bar(a b, c d);
    void baz(a b, c …
Run Code Online (Sandbox Code Playgroud)

c++ pimpl-idiom

8
推荐指数
1
解决办法
424
查看次数

如何返回通用迭代器(独立于特定容器)?

我想设计一个类Foo来存储不同类型的各种数据并返回它们的迭代器。它应该是通用的,因此用户Foo不知道数据是如何存储的(Foo可能正在使用std::setstd::vector其他)。

我很想写一个这样的界面:

class Foo {
  class FooImpl;
  FooImpl* impl_;
public:
  const Iterator<std::string>& GetStrings() const;
  const Iterator<int>& GetInts() const;
};
Run Code Online (Sandbox Code Playgroud)

哪里Iterator有类似这样的东西(比如 .NET 中的迭代器):

template<class T>
class Iterator {
public:
  const T& Value() const = 0;
  bool Done() const = 0;
  void Next() = 0;
};
Run Code Online (Sandbox Code Playgroud)

但我知道这种迭代器在C++中不是标准的,最好像STL那样使用迭代器,这样你就可以在它们上使用STL算法。

我怎样才能做到这一点?(我有需要iterator_traits吗?)

c++ iterator stl pimpl-idiom

7
推荐指数
1
解决办法
4073
查看次数

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

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

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

BananaTree.h:

class Banana;

class BananaTree
{
public:
  virtual Banana* getBanana(std::string const& name) = 0;

  static BananaTree* create(std::string const& name);
};
Run Code Online (Sandbox Code Playgroud)

BananaTree.cpp:

class BananaTreeImpl : public BananaTree
{
private:
  string name;

  Banana* findBanana(string const& name)
  {
    return //obtain banana, somehow;
  }

public:
  BananaTreeImpl(string name) 
    : name(name)
  {}

  virtual Banana* getBanana(string const& name)
  {
    return findBanana(name);
  }
};

BananaTree* BananaTree::create(string const& name)
{
  return new BananaTreeImpl(name);
}
Run Code Online (Sandbox Code Playgroud)

这里唯一的麻烦就是我不能使用new,而必须打电话BananaTree::create().我不认为这确实是一个问题,特别是因为我希望无论如何都要使用很多工厂.

然而,现在,C++成名的聪明人提出了另一个解决方案,即pImpl成语.有了它,如果我理解正确,我的代码将如下所示:

BananaTree.h:

class BananaTree
{
public: …
Run Code Online (Sandbox Code Playgroud)

c++ pimpl-idiom header pure-virtual

7
推荐指数
1
解决办法
1445
查看次数

C++:自动减少编译时依赖性的工具

在阅读了关于pimpl成语之后,我感到震惊!

是不是有一个工具可以检查.h/.cpp文件并推断可以放弃哪些依赖项?

c++ pimpl-idiom dependency-management

7
推荐指数
1
解决办法
943
查看次数

没有malloc的完整封装

我正在试验C11和VLA,试图在堆栈上声明一个只有不完整声明的结构变量.目标是提供一种机制来创建一些结构类型的变量而不显示内部(如PIMPL惯用法),但不需要在堆上创建变量并返回指向它的指针.此外,如果结构布局发生更改,我不想重新编译使用该结构的每个文件.

我设法编写了以下内容:

private.h:

#ifndef PRIVATE_H_
#define PRIVATE_H_

typedef struct A{
    int value;
}A;

#endif /* PRIVATE_H_ */
Run Code Online (Sandbox Code Playgroud)

public.h:

#ifndef PUBLIC_H_
#define PUBLIC_H_

typedef struct A A;

size_t A_getSizeOf(void);

void A_setValue(A * a, int value);

void A_printValue(A * a);

#endif /* PUBLIC_H_ */
Run Code Online (Sandbox Code Playgroud)

implementation.c:

#include "private.h"
#include "stdio.h"

size_t A_getSizeOf(void)
{
    return sizeof(A);
}

void A_setValue(A * a, int value)
{
    a->value = value;
}

void A_printValue(A * a)
{
    printf("%d\n", a->value);
}
Run Code Online (Sandbox Code Playgroud)

main.c中:

#include <stdalign.h>
#include <stddef.h>

#include "public.h"

#define …
Run Code Online (Sandbox Code Playgroud)

c pimpl-idiom c99 variable-length-array c11

7
推荐指数
1
解决办法
763
查看次数

为什么要将pimpl声明为结构而不是类?

pimpl习语的规范形式(来自Herb Sutter的"Exceptional C++")如下:

class X 
{
public:
 /* ... public members ... */
protected:
 /* ... protected members? ... */ 
private:
 /* ... private members? ... */
 struct XImpl;
 XImpl* pimpl_; // opaque pointer to
                // forward-declared class 
};
Run Code Online (Sandbox Code Playgroud)

我的问题是,为什么XImpl声明为结构而不是类?

c++ pimpl-idiom

7
推荐指数
2
解决办法
697
查看次数

如何测量pimpl候选人?

pimpl(也称为编译器防火墙)习惯用于缩短编译时间,但代价是可读性和一点运行时性能.目前一个项目需要很长时间才能编译,如何衡量最佳的pimpl候选人?

我有使用pimpl的经验,将项目的编译时间从两小时缩短到十分钟,但我只是按照我的直觉做了这个:我推断出类头文件包括(1)很多源代码(2)复杂/模板类,是使用疙瘩成语的最佳人选.

是否有一个工具可以客观地指出哪些类是优秀的pimpl候选人?

c++ profiler pimpl-idiom

6
推荐指数
1
解决办法
151
查看次数