标签: pimpl-idiom

没有堆的pimpl.不正确还是迷信?

我渴望将接口与实现分开.这主要是为了保护使用库的代码来改变所述库的实现,尽管减少编译时间肯定是受欢迎的.

对此的标准解决方案是指向实现习惯用法的指针,最有可能通过使用unique_ptr并使用实现仔细定义类析构函数来实现.

这不可避免地引起了对堆分配的担忧.我熟悉"让它工作,然后快速完成","简介再优化"等智慧.还有在线文章,例如gotw,它宣称明显的解决方法是脆弱和不可移植.我有一个目前不包含任何堆分配的库 - 我想保持这种方式 - 所以让我们有一些代码.

#ifndef PIMPL_HPP
#define PIMPL_HPP
#include <cstddef>

namespace detail
{
// Keeping these up to date is unfortunate
// More hassle when supporting various platforms
// with different ideas about these values.
const std::size_t capacity = 24;
const std::size_t alignment = 8;
}

class example final
{
 public:
  // Constructors
  example();
  example(int);

  // Some methods
  void first_method(int);
  int second_method();

  // Set of standard operations
  ~example();
  example(const example &);
  example &operator=(const example &); …
Run Code Online (Sandbox Code Playgroud)

c++ pimpl-idiom c++11

13
推荐指数
1
解决办法
371
查看次数

委托私人部分

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

class Foo
{
    struct Bar;
    Bar* p;

public:

    Bar* operator->() const
    {
        return p;
    }
};

struct Foo::Bar
{
    void baz()
    {
        std::cout << "inside baz\n";
    }
};

int main()
{
    Foo::Bar b;   // error: 'struct Foo::Bar' is private within this context

    Foo f;
    f->baz();     // fine
}
Run Code Online (Sandbox Code Playgroud)

自从Foo::Bar就是private,我不能宣布bmain.然而,我可以从方法中调用方法Foo::Bar.为什么这是允许的?这是意外还是设计?


哦等等,它会变得更好:

Foo f;
auto x = f.operator->();   // :-)
x->baz();
Run Code Online (Sandbox Code Playgroud)

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


诺亚写道:

在类定义中定义的类型名称不能在没有限定条件的类之外使用.

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

#include <type_traits> …
Run Code Online (Sandbox Code Playgroud)

c++ pimpl-idiom private delegation operator-overloading

12
推荐指数
1
解决办法
422
查看次数

自动化C++类的pimpl - 有一个简单的方法吗?

Pimpl是许多C++代码中的样板来源.它们似乎是宏,模板和一些外部工具帮助可以解决的组合,但我不确定最简单的方法是什么.我已经看到模板有助于完成一些提升但不是很多 - 你仍然需要为你试图包装的类的每个方法编写转发函数.有没有更简单的方法?

我正在想象一个用作制作过程一部分的工具.你希望你的公共标题是pimpl'd类,所以你提供一些输入文件,比如pimpl.in,列出你要包装的类(实现un-pimpl'd),然后检查该文件,生成pimpl类,并且在'make install'期间只安装它们的标题(不是原始类的标题).问题是如果没有完整的C++解析器,我没有看到任何方法可以做到这一点,甚至编译器供应商都无法做到这一点.也许这些类可以用某种方式编写,这使得外部工具的工作变得更容易,但我确信我最终会错过各种角落案例(例如模板化类和/或模板化成员函数).

有任何想法吗?有没有其他人为此问题提供解决方案?

c++ macros templates build-process pimpl-idiom

11
推荐指数
1
解决办法
1324
查看次数

使用d指针的优点和缺点是什么?

d指针在Qt中大量使用,它们是pimpl习语的实现.我知道pimpl成语的优点和缺点.但我错过了d-pointers实现的优点.这里这里是d指针的样本.使用它不是更容易吗?

class MyClassPrivate;
class MyClass {
  // interface methods
private:
  MyClassPrivate *pimpl_;
};
Run Code Online (Sandbox Code Playgroud)

c++ qt pimpl-idiom

11
推荐指数
2
解决办法
6286
查看次数

Java编程习语:私有实现类

我在一些代码中找到了这个构造.

私有静态类实现A有什么好处吗?这让我想起了C++中的Pimpl成语.在Java中使用Pimpl习语是否有任何好处?

public abstract class A {
    public void doStuff();

    public static A getNewInstance() {
       return new AImpl();
    }

    private static class AImpl extends A {
        public void doStuff()  {
           ....
        }    
    } 

}
Run Code Online (Sandbox Code Playgroud)

java pimpl-idiom private-members private-class

11
推荐指数
1
解决办法
2717
查看次数

使用指针隐藏实现(Pimpl idiom)

是否可能,以实现以下目标:

x.hpp - 许多其他类都包含此文件

class x_impl; //forward declare
class x {
    public:
        //methods...
    private:
        x_impl* impl_;
};
Run Code Online (Sandbox Code Playgroud)

x.cpp - 实现

#include <conrete_x>
typedef concrete_x x_impl;    //obviously this doesn't work
//implementation of methods...
Run Code Online (Sandbox Code Playgroud)

所以基本上,我希望用户包含文件x.hpp,但不知道conrete_x.hpp标头.

由于我concrete_x只能通过指针使用并且它只显示为私有数据成员,因此前向声明应该足以让编译器知道准备多少空间.它看起来很像着名的"pimpl成语".

你能帮帮我吗?

PS.我不想使用它void*并将其投射..

c++ dependencies pimpl-idiom

11
推荐指数
2
解决办法
4431
查看次数

用最少量的代码实现pImpl

可以使用哪种技巧来最小化实现pImpl类的工作量?

标题:

class Foo {
    struct Impl;
    boost::scoped_ptr<Impl> self;
public:
    Foo(int arg);
    ~Foo();
    // Public member functions go here
};
Run Code Online (Sandbox Code Playgroud)

执行:

struct Foo::Impl {
    Impl(int arg): something(arg) {}
    // All data members and private functions go here
};

Foo::Foo(int arg): self(new Impl(arg)) {}
Foo::~Foo() {}

// Foo's public functions go here (and they refer to data as self->something)
Run Code Online (Sandbox Code Playgroud)

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

c++ boost pimpl-idiom

10
推荐指数
1
解决办法
2190
查看次数

Pimpl with smart ptr - 为什么需要构造函数/析构函数

让我们考虑以下示例(使用c ++ 11)

A.hpp:

#include <memory>
class A
{
  public:
    //A();
    //~A();

  private:
    struct AImpl;
    std::unique_ptr<AImpl> pImpl;
};
Run Code Online (Sandbox Code Playgroud)

main.cpp中:

#include "A.hpp"

int main()
{
    A a;
}
Run Code Online (Sandbox Code Playgroud)

使用默认构造函数和析构函数.不编译.发生以下错误:

在文件中包含/usr/include/c++/4.8/memory:81:0,来自A.hpp:2,来自main.cpp:2:/usr/include/c++/4.8/bits/unique_ptr.h:实例化'void std :: default_delete <_Tp> :: operator()(_ Tp*)const [with _Tp = A :: AImpl]':/ usr /include/c++/4.8/bits/unique_ptr.h:184:16: 'std :: unique_ptr <_Tp,_Dp> ::〜unique_ptr()[与_Tp = A :: AImpl; _Dp = std :: default_delete]'A.hpp:3:7:从这里需要/usr/include/c++/4.8/bits/unique_ptr.h:65:22:错误:'sizeof'无效应用于不完整类型' A :: AImpl'static_assert
(sizeof(_Tp)> 0,

使用boost :: scoped_ptr而不是std :: unique_ptr时会发生类似的错误.我是否理解正确 - 这意味着,AImpl的前向声明是不够的?

添加构造函数和析构函数时,一切正常.是什么原因?是因为默认是内联的,因此看不到AImpl的大小?在添加构造函数和析构函数时,编译器假定这些定义知道AImpl的大小?

c++ pimpl-idiom c++11

10
推荐指数
1
解决办法
1282
查看次数

为什么"错误:使用unique_ptr将'sizeof'无效应用于不完整类型"通过添加空析构函数来修复?

我正在上课STFT.在标题中编译就好了:

class STFT; // pimpl off to prevent point name clash

class Whatever
{
private:
    STFT* stft;
Run Code Online (Sandbox Code Playgroud)

这在实施中:

#include "STFT.h"
Whatever::Whatever() : stft(new STFT()) {
// blah blah
}

Whatever::~Whatever() {
    delete stft; // pure evil
}
Run Code Online (Sandbox Code Playgroud)

但是,切换到std::unique_ptr<STFT> stft;标题中的原始指针,并删除析构函数,我得到

错误:'sizeof'无效应用于不完整类型'STFT'static_assert(sizeof(_Tp)> 0,"default_delete无法删除不完整类型");

但是,如果我只提供一个空的析构函数Whatever::~Whatever(){},那么它编译得很好.这让我完全难过.请填写我这个毫无意义的析构函数为我做的事情.

c++ pimpl-idiom unique-ptr c++11

9
推荐指数
2
解决办法
6329
查看次数

您使用什么模式来分离C++中的接口和实现?

大型C++项目中的一个问题可能是构建时间.您的依赖树中有一些类需要处理,但通常您会避免这样做,因为每个构建都需要很长时间.您不一定要更改其公共接口,但也许您想要更改其私有成员(添加缓存变量,提取私有方法,...).您面临的问题是,在C++中,甚至私有成员都在公共头文件中声明,因此您的构建系统需要重新编译所有内容.

你在这种情况下做了什么?

我已经勾画了两个我所知道的解决方案,但它们都有它们的缺点,也许还有一个我尚未想到的更好的解决方案.

c++ pimpl-idiom delegation

8
推荐指数
2
解决办法
2000
查看次数