- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
请考虑下面的代码。
模板参数是一个处理程序类,必须提供函数bar()
。
我正在使用 Pimpl 习惯用法来隐藏 Foo
的实现细节。在使用模板参数之前,构造函数定义在 foo.cpp
中,一切都很好。
///////////
// foo.h
///////////
class Foo
{
public:
template <class Handler>
Foo(Handler& handler);
void someFunction();
private:
/** Private implementation details. */
struct Impl;
const std::unique_ptr<Impl> m_impl;
};
template <class Handler>
Foo::Foo(Handler& handler) : m_impl{new Impl{handler}}
{
}
///////////
// foo.cpp
///////////
#include "foo.h"
/** Encapsulates the private implementation details of Foo. */
struct Foo::Impl
{
public:
Impl(Handler& handler) : m_handler(handler)
{
}
void someOtherFunction()
{
m_handler->bar();
}
private:
Handler& m_handler;
friend class Foo;
};
void Foo::someFunction()
{
m_impl->someOtherFunction();
}
引入模板参数后,我不得不将构造函数放在 foo.h
中,这会导致以下编译器错误:
不完整类型“Foo::Impl”的分配
。
我理解我收到错误的原因,但我想不出解决它的办法,仍然使用 Pimpl 习惯用法。
有人能帮忙吗?
最佳答案
您可以使用或不使用虚函数来解决这个问题。第一个选项稍微简单一些:使用虚函数,或者用于 Handler
class HandlerBase { .... virtual void bar() = 0; ... };
class Foo { ... std::unique_ptr<HandlerBase> handler; ... };
或用于实现
class ImplBase { ... virtual void someFunction() = 0; }
class Foo { ... std::unique_ptr<ImplBase> m_impl; ... }
template<typename Handler> class Impl : public ImplBase { ... Handler& m_handler; ...};
我认为这些实现起来相对简单。您可以看到,在使用 HandlerBase 时,您甚至不需要 pimpl 习惯用法。
另一种选择是使用 The Impossibly Fast C++ Delegates方法:
class Foo
{
public:
template <class Handler>
explicit Foo(Handler& handler)
: handler(&handler) {
someFunctionInstance = someFunctionTemplate<Handler>;
}
void someFunction() {
someFunctionInstance(handler);
}
private:
typedef void (*SomeFunctionType)(void* handler);
void* handler;
SomeFunctionType someFunctionInstance;
template<typename Handler>
static void someFunctionTemplate(void* handler) {
static_cast<Handler*>(handler)->bar();
}
};
Foo 的类型仍然独立于 Handler。构造函数中的赋值创建了 someFunctionTemplate 的自定义实例,它能够调用实际的 Handler 类型。 SomeFunctionInstance 是 Handler 模板实例化的结果,但由于它是静态函数,因此其类型也独立于 Handler。
但是这个解决方案很棘手并且确实包含一个 reinterpret_cast,它仍然是完全类型安全的。
关于c++ - 依赖模板函数的 Pimpl 习语实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29103193/
我有两个实现 PIMPL 的类:State 和 StateMachine。 它们实现了 Private::State 和 Private::StateMachine。 Private::StateMa
考虑以下两种实现 pimpl 习语的方法: // file g_visible.h //global forward declarations class HiddenStuff_A; class
我目前正在研究pimpl idiom,并且有非常好的教程介绍如何实现它(例如 here )。但我从未见过它像这样作为基本模板类实现: #ifndef PIMPL_H #define PIMPL_H t
这个问题在这里已经有了答案: Move semantics == custom swap function obsolete? (5 个答案) 关闭 2 年前。 我有几个基于 PIMPL 习语的类(
我正在开发一个小型 IO 库,其中接口(interface)的要求是已知的,但实现可能会发生变化。该库应该以存档格式读取和写入文件,并存储一些元数据。 我考虑过使用 pimpl,因为它似乎非常适合这项
我正在尝试为 pimpl idiom 创建一个实用程序类,但是我遇到了一些问题,希望得到一些帮助: 这就是我得到的: [sehe:另请参阅此处的 rev.1:https://gist.github.c
请看下面的代码(一代码胜一千字): 形状.hpp class Shape { public: double area() const; private: class ShapeImpl
我想更好地理解如何在 PIMPL 习语存在的情况下使用静态字段方法。考虑以下代码。 MyClass.h 文件: #ifndef MYCLASS #define MYCLASS class MyClas
假设我有一个 B 类型的对象,并调用 B.foo(),其中 foo() 是定义的方法在 A 中并且尚未在 B 中重新定义。 A::foo() 有 impl->foo() 行。 当我们调用 B.foo(
我正在从 http://en.wikibooks.org/wiki/C%2B%2B_Programming/Code/Design_Patterns#Creational_Patterns 中阅读有关
我正在使用 pimpl 惯用法实现几个类,并且遇到了一些设计问题。 首先,我一直看到pimpl是这样做的 class Object { public: Visible(); ~Visi
.h public: void doStuff() const; private: struct Private; Private * d; .cpp struct XX::P
所以我一直在思考PIMPL和堆栈分配。我一直在编写一个库,并决定使用 PIMPL 来隐藏该类的私有(private)成员。这意味着我将有一个这样声明的类 class Foo { private:
我正在尝试使用 pimpl 模式并在匿名命名空间中定义实现类。这在 C++ 中可能吗?我失败的尝试如下所述。 是否可以在不将实现移动到具有名称(或全局名称)的 namespace 的情况下解决此问题?
考虑以下几点: PImpl.hpp class Impl; class PImpl { Impl* pimpl; PImpl() : pimpl(new Impl) { } ~
可以使用什么样的技巧来最小化实现 pImpl 类的工作量? 标题: class Foo { struct Impl; boost::scoped_ptr self; public:
请参阅我的 PIMPL 继承实现。在派生类中,DerivedImpl继承自BaseImpl。 问题:指向 Impl 的指针是否应该像下面的代码一样只在基类中定义?如果是这样,每次我需要使用基指针时,我
这是一个非常愚蠢的错误,但我不知道这里发生了什么。 有很多 pimpl 示例,但我不明白为什么这不起作用(这或多或少是示例之一,但我看不出有什么区别)。 我有一个非常简单的 Pimpl 示例,但它不起
在我的新工作场所,代码大量使用 Pimpl 惯用语,原因是为了减少编译时间。但是我有一个基本的查询——pimpl 不需要动态分配内存吗?因此,实际上我们在堆中分配了比需要更多的内存。如果它被大量使用,
考虑下一个简单的例子: 标题: // a.hpp #ifndef A_HPP #define A_HPP #include class A { public: A(); int foo()
我是一名优秀的程序员,十分优秀!