标签: pimpl-idiom

C++ pimpl成语浪费了一个指令与C风格?

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

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

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

下面是我的Mac上的文件,命令和机器代码.

thing.hh:

class ThingImpl;
class Thing
{
    ThingImpl *impl;
public:
    Thing();
    int calc();
};

class OtherThing;    
OtherThing *make_other();
int calc(OtherThing *);
Run Code Online (Sandbox Code Playgroud)

thing.cc:

#include "thing.hh"

struct ThingImpl
{
    int x;
};

Thing::Thing()
{
    impl = new ThingImpl;
    impl->x = 5;
}

int Thing::calc()
{
    return impl->x + 1;
}

struct OtherThing
{
    int x;
};

OtherThing *make_other()
{
    OtherThing *t …
Run Code Online (Sandbox Code Playgroud)

c++ optimization pimpl-idiom

6
推荐指数
2
解决办法
1763
查看次数

将所有方法放在类定义中

当我使用pimpl习语时,将所有方法定义放在类定义中是否是个好主意?例如:

// in A.h

class A {
   class impl;
   boost::scoped_ptr<impl> pimpl;
public:
   A();
   int foo();
}

// in A.cpp

class A::impl {
   // method defined in class
   int foo() {
       return 42;
   }

   // as opposed to only declaring the method, and defining elsewhere:
   float bar();
};

A::A() : pimpl(new impl) { }
int A::foo() {
   return pimpl->foo();
}
Run Code Online (Sandbox Code Playgroud)

据我所知,将方法定义放在类定义中的唯一问题是(1)实现在包含类定义的文件中可见,(2)编译器可以使方法内联.

在这种情况下,这些不是问题,因为类是在私有文件中定义的,并且内联没有任何效果,因为只在一个地方调用方法.

将定义放在类中的优点是您不必重复方法签名.

那么,这样可以吗?还有其他问题需要注意吗?

c++ pimpl-idiom inline

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

关于封装的Code Complete的C++建议?

在Code Complete中的"Good Encapsulation"部分中,建议隐藏私有实现细节.C++中给出了一个例子.这个想法基本上是将接口与实现完全分开,即使在类级别也是如此.

class Employee {
public:
    ...
    Employee( ... );
    ...

    FullName GetName() const;
    String GetAddress() const;

private:
    EmployeeImplementation *m_implementation;
};
Run Code Online (Sandbox Code Playgroud)

这真的很好用吗?这不仅效率低下(这会带来什么样的性能损失?),但Code Complete("管理复杂性")的整个座右铭似乎已经被逆转 - 这不会增加复杂性吗?

c++ pimpl-idiom access-specifier code-complete

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

模板中的pimpl-idiom; 哪个智能指针?

我通常对pimpl使用boost :: scoped_ptr(出于一个原因,因为如果我忘记处理复制构造函数,我就不会感到惊讶)

但是,使用模板,我不能将析构函数放在完全定义impl的cpp文件中,以满足scoped_ptr析构函数的要求.无论如何它确实有效,但我不确定它是否能够保证工作或只是偶然.有一些"最佳实践"或标准吗?scoped_ptr是非可复制类中pimpls的最佳智能指针吗?

template <class T> class C {
public:
    C(){}
    ~C(){}
private:
    boost::scoped_ptr<T> pimpl_;
};
Run Code Online (Sandbox Code Playgroud)

c++ templates boost pimpl-idiom scoped-ptr

6
推荐指数
2
解决办法
2168
查看次数

Pimpl成语指向可配置的实现

我已经读过Pimpl有利于二进制兼容性,接口有利于轻松切换实现.我需要结合这两种技术,以便我的应用程序能够通过配置文件切换底层实现.

以下是我当前设计的布局:

Foo类:提供面向客户的API,我很担心ABI兼容性这里
一流的IFoo:接口类(所有的纯虚方法,虚析构函数)
类Vendor1Foo:实现IFoo的,使用的供应商1的库
类Vendor2Foo:实现IFoo的,使用供应商2的图书馆

通过不使用pimpl并严格使用接口,客户端代码可能如下所示:

IFoo* foo = new Vendor1Foo();
Run Code Online (Sandbox Code Playgroud)

问题是我的客户端代码根本无法了解Vendor1或Vendor2,而Foo只是我必须执行此操作的众多类之一.

我正在尝试做的所有概念如下:

class foo
{
  private:
  QScopedPointer<IFoo> pimpl;
  void initImpl();  // Reads from QSettings and initializes pimpl
}
Run Code Online (Sandbox Code Playgroud)

有什么想法可以优雅地解决这个问题吗?

我希望能够提出一些宏或模板类/方法来帮助标准化我如何处理这个并最大限度地减少违反DRY.

模板类可以作为一个辅助性PIMPL像香草萨特的大上广义PIMPL方法对C++ 11:herbsutter.com/gotw/_101,它也必须包含逻辑实例根据配置的正确实施

这里有pimpl成语,桥梁模式和工厂模式的元素.在上面的例子中,initImpl()可以被认为是一个工厂方法.我正在寻找可能会或可能不会使用所有这些模式的解决方案.

我已经看过c ++ pimpl习语:实现取决于模板参数以及SO上的大多数pimpl习语问题.标题似乎很有希望,但它对我的特定用例没有帮助.

我不能使用C++ 11并使用Qt. D-Pointers无法解决我的问题,因为它们绑定到单个实现.

c++ qt pimpl-idiom interface factory-pattern

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

内部类,pimpl和朋友类 - 不同意编译器

我在一些旧的库代码中捣乱,其基本目标是重构它.这个旧代码并不完全符合最佳实践和美观(是的 - 朋友很糟糕,并且在发现下面之后它已被删除 - 因为它是重构的疏忽).

现在准备运行一些单元测试我用clang ++,g ++和vc ++编译了代码(2005年 - 是的,我知道它已经过时了,但为了向后兼容 - 我必须这样做).

g ++和clang ++编译并运行没有错误,但Visual C++抱怨,所以在查看代码后,我发现了一些效果:

#include <iostream>

class one {

  private:
    struct private_impl;
    private_impl* pimpl_;

  public:
    one();
    ~one();
    void say_hello();
};

class two {

  private:
    friend class one;
    void say_world();

  public:

};

struct one::private_impl {
  two t;
  void say_world();
};

void one::private_impl::say_world() {
   std::cout << " ";
   t.say_world();  //This should not work should it?
}

one::one() : pimpl_(new private_impl) { }

one::~one() {
  delete pimpl_;
}

void one::say_hello() …
Run Code Online (Sandbox Code Playgroud)

c++ pimpl-idiom friend inner-classes language-lawyer

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

使用pimpl移动类将无法编译

在下面的例子中,如何正确调用~CImpl,但是当需要移动类时,编译器说它有一个不完整的类型?

如果Impl的声明被移动到它工作的标题,我的问题是如何将析构函数调用为好,所以它似乎不是类型不完整,但移动时出现问题.

档案:C.hpp

#include <memory>

class Impl;


class C
{
public:
    C();
    ~C();

    C(C&&) = default;
    C& operator=(C&&) = default;

    std::unique_ptr<Impl> p;
};
Run Code Online (Sandbox Code Playgroud)

档案C.cpp

#include "C.hpp"
#include <iostream>

using namespace std;

class Impl
{
public:
    Impl() {}
    virtual ~Impl() = default;
    virtual void f() = 0;
};

class CImpl: public Impl
{
public:
    ~CImpl()
    {
        cout << "~CImpl()" << endl;
    }
    void f()
    {
        cout << "f()" << endl;
    }

};


C::C():
    p(new CImpl())
{}

C::~C()
Run Code Online (Sandbox Code Playgroud)

file:main.cpp

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

c++ pimpl-idiom opaque-pointers c++11

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

如何测量pimpl候选人?

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

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

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

c++ profiler pimpl-idiom

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

Pimpl with unique_ptr:为什么我必须将接口构造函数的定义移动到".cpp"?

只要我不将构造函数(of B)的定义移动到头部,代码就会工作B.h.

BH

class Imp;  //<--- error here
class B{
    public:
    std::unique_ptr<Imp> imp;
    B();     //<--- move definition to here will compile error
    ~B();
    //// .... other functions ....
};
Run Code Online (Sandbox Code Playgroud)

B.cpp

#include "B.h"
#include "Imp.h"
B::B(){ }
~B::B(){ }
Run Code Online (Sandbox Code Playgroud)

Imp.h

class Imp{};
Run Code Online (Sandbox Code Playgroud)

Main.cpp (编译我)

#include "B.h"
Run Code Online (Sandbox Code Playgroud)

错误:删除指向不完整类型的指针
错误:使用未定义类型'Imp'C2027

我可以以某种方式理解析构函数必须被移动到.cpp,因为Imp可能会被称为析构: -

delete pointer-of-Imp;  //something like this
Run Code Online (Sandbox Code Playgroud)

但是,我不明白为什么规则也涵盖了构造函数(问题).

我读过了 :-

c++ pimpl-idiom unique-ptr

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

即将在 C++ 中添加的模块是否会修复/减轻对 pimpl 习惯用法的需求?

据我所知,pimpl 习惯用法将私有实现隐藏在前向声明的符号名称后面,以便可以在私有 cpp 模块中声明和使用它。

示例: https: //cpppatterns.com/patterns/pimpl.html

据我所知,因为 pimpl 类 hosint 需要了解其结构(大小、对齐方式),所以 pimpl 必须通过某种指针是间接的。

(或分配为足够大小的块,然后移动/创建到稍后通过强制转换重新解释的位置。)

即将推出的模块规范是否以任何方式解决这个问题?

c++ pimpl-idiom c++-modules

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