隐藏PIMPL-Objects拥有的成员的实现
Hiding implementation of members owned by PImpl-objects
我有一个我想创建一个界面的类,而无需显示任何实现(不是因为它是封闭的源),让我们称之为foo。我知道这通常是通过pimpl-idiom或虚拟接口完成的,我已经实现了该类别的pimpl-idiom。
但是,此类具有公共功能,可以返回其他也包括这些标题的类foo.h.但是,这些类在库中大量使用,因此我不想用PIMPL实现它们,因为这会引入很多开销(它们在3D渲染器的代码中经常使用)。让我们称其中一个酒吧:
foo.h:
#include "Bar.h"
class Foo
{
private:
class impl;
std::unique_ptr<impl> m_pimpl;
public:
Foo();
Bar& get_bar();
};
foo.cpp:
#include "Foo.h"
class Foo::impl {
private:
Bar m_bar;
public:
Bar& get_bar();
};
Foo::Foo() : m_pimpl{std::make_unique<impl>()}
{ }
Bar& Foo::get_bar() {
return m_pimpl->get_bar();
}
为此,我需要#include" bar.h",但是bar.h可能包括我想隐藏的标题。这也让我可以选择让酒吧使用pimpl-idiom,但是我不希望酒吧的开销,因为bar在foo内部在内部使用了很多。但是,我想出了一种解决这个问题的方法,但是我对此并不确定,因为我以前从未看到过它:
使用PIMPL而不拥有指针/参考来简单地包装一类并为其创建接口。这样,只有当foo的外部时,开销才适用,但在内部仍将使用非包裹类。
例如,假设PBAR正在包装栏:
pbar.h:
class Bar;
class PBar {
private:
Bar &m_bar;
public:
explicit PBar(Bar &bar);
void do_stuff();
};
pbar.cpp:
#include "PBar.h"
#include "../impl/Bar.h" // This is the actual Bar implementation
PBar::PBar(Bar &bar) : m_bar(bar) {
}
void PBar::do_stuff() {
m_bar.do_stuff();
}
和foo在创建时实例化PBAR,并引用对象内的实际栏:
foo.h
#include "PBar.h"
class Foo
{
private:
class impl;
std::unique_ptr<impl> m_pimpl;
PBar m_bar;
public:
Foo();
PBar& get_bar() { return m_bar; }
};
foo.cpp:
class Foo::impl {
private:
Bar m_bar;
public:
Bar& get_bar();
};
Foo::Foo() : m_pimpl{std::make_unique<impl>()},
m_bar(impl->get_bar())
{ }
这种模式曾经使用过吗?我还有其他方法可以解决这个问题吗?它或多或少与Pimpl相同,但是我还没有想到什么不好?肯定感觉更干净,但是我看不出如何以其他方式完成此操作。
另外,我希望pbar或bar在FOO外面构造,所以这不是问题。
谢谢!
您不能(不应该)更改参考成员引用的对象:您在这里如何执行:Foo a,b; a=b;
(假设您初始化非NULL null unique_ptr)。这很容易纠正用指针替换参考。
这个看起来像是一个好主意,您要做的就是缓存放弃。但是您正在失去pimpl成语的某些效率,并且正在使Foo
的大小加倍。
您是否考虑过制作class impl
标准布局并将Bar
放在impl
内的已知偏移量:
foo.h
constexpr auto impl_bar_offset = 8;
//...
class Foo{
private:
class impl;
std::unique_ptr<impl> m_impl;
public:
bar& get_bar(){
assert(m_impl);
return *reinterpret_cast<bar*>(
reinterpret_cast<unsigned char*>(m_impl.get())+impl_bar_offset);
}
};
foo.cpp
class impl{
long a_long;
bar a_bar;
//...
};
static_assert(impl_bar_offset==offsetof(impl,a_bar));
- 三向比较运算符成员与非成员实现
- 多次实现成员功能
- 可以具有不同基成员实现的类的最佳实现
- 如何为非常量和常量重载实现一次成员函数?
- 基于自定义void_t实现的成员检测
- 将C++子类成员函数(虚拟实现)传递给 C 类型函数指针
- C++ 20 中的运算符 == 和 <=> 应该作为成员还是自由函数实现?
- 如何为具有私有成员的派生类实现移动构造函数
- 在C++中实现类似 python "map"函数的问题:调用类成员函数
- 在C++中使用链表的堆栈实现中,访问结构体headNode成员count和top会导致运行时错误
- C++ 入门 12.1:我可以在类中使用静态向量成员实现 StrBlob<string> 吗?
- 使用 PIMPL 惯用法,实现是否应始终是类的私有成员?
- 如何将已实现的虚拟成员函数作为参数传递
- std::add_pointer 非静态成员函数的实现
- 为什么在std::optional的某些实现中有一个虚拟工会成员?
- 成员功能C 的不同实现
- 在.cpp文件中实现时访问私有成员
- 是否可以使用抛出交换成员实现?
- 如何在cpp文件中为多个类型创建模板类成员实现?
- 用int成员实现哪些操作符