C++ PImpl习惯用法,在单独的源文件中使用std::unique_指针和实现类
我正在编写一个简单的库来处理跨不同平台的窗口创建。为了抽象出特定于平台的代码,我想使用带有std::unique\u ptr的PImpl习惯用法,并提供一个带有工厂函数的特定于平台的私有实现。这就是我目前拥有的: Window.h:C++ PImpl习惯用法,在单独的源文件中使用std::unique_指针和实现类,c++,smart-pointers,pimpl-idiom,C++,Smart Pointers,Pimpl Idiom,我正在编写一个简单的库来处理跨不同平台的窗口创建。为了抽象出特定于平台的代码,我想使用带有std::unique\u ptr的PImpl习惯用法,并提供一个带有工厂函数的特定于平台的私有实现。这就是我目前拥有的: Window.h: #pragma once #include <memory> class Window { public: Window(); ~Window(); private: class WindowImpl;
#pragma once
#include <memory>
class Window
{
public:
Window();
~Window();
private:
class WindowImpl;
std::unique_ptr<WindowImpl> impl;
};
#include "Window.h"
#include "WindowImpl.h"
Window::Window() : impl(WindowImpl::create()) {}
Window::~Window() = default;
#include "Window.h"
#include <memory>
class Window::WindowImpl
{
public:
static std::unique_ptr<WindowImpl> create();
};
#include "WindowImpl.h"
std::unique_ptr<Window::WindowImpl> Window::WindowImpl::create()
{
// the plan is to return the platform specific WindowImpl implementation here
return std::make_unique<Window::WindowImpl>();
}
WindowImpl.h:
#pragma once
#include <memory>
class Window
{
public:
Window();
~Window();
private:
class WindowImpl;
std::unique_ptr<WindowImpl> impl;
};
#include "Window.h"
#include "WindowImpl.h"
Window::Window() : impl(WindowImpl::create()) {}
Window::~Window() = default;
#include "Window.h"
#include <memory>
class Window::WindowImpl
{
public:
static std::unique_ptr<WindowImpl> create();
};
#include "WindowImpl.h"
std::unique_ptr<Window::WindowImpl> Window::WindowImpl::create()
{
// the plan is to return the platform specific WindowImpl implementation here
return std::make_unique<Window::WindowImpl>();
}
#包括“Window.h”
#包括
类窗口::WindowImpl
{
公众:
静态std::unique_ptr create();
};
WindowImpl.cpp:
#pragma once
#include <memory>
class Window
{
public:
Window();
~Window();
private:
class WindowImpl;
std::unique_ptr<WindowImpl> impl;
};
#include "Window.h"
#include "WindowImpl.h"
Window::Window() : impl(WindowImpl::create()) {}
Window::~Window() = default;
#include "Window.h"
#include <memory>
class Window::WindowImpl
{
public:
static std::unique_ptr<WindowImpl> create();
};
#include "WindowImpl.h"
std::unique_ptr<Window::WindowImpl> Window::WindowImpl::create()
{
// the plan is to return the platform specific WindowImpl implementation here
return std::make_unique<Window::WindowImpl>();
}
#包括“WindowImpl.h”
std::unique_ptr Window::WindowImpl::create()
{
//计划在此处返回特定于平台的WindowImpl实现
返回std::make_unique();
}
这似乎是我想要的。我的问题是,我目前必须在WindowImpl.cpp中的所有内容前面指定“Window::”。因为Window是一个类而不是命名空间,“使用Window”不起作用。我找到的关于这个主题的示例都在使用它的类的源文件中有完整的Impl类定义,因此没有这个问题。但是如果我想从中派生特定于平台的实现,我需要在一个单独的头中包含WindowImpl
有没有办法将WindowImpl保存在自己的头文件/源文件中并消除这种冗长的内容?但是,您可以使用类型别名,这将要求您将嵌套类公开,这可能会妨碍PImpl习惯用法的使用:
using WImpl = typename Window::WindowImpl;
std::unique_ptr<WImpl> WImpl::create(){
//implementation goes here
}
使用WImpl=typename窗口::WindowImpl;
std::unique_ptr WImpl::create(){
//实现就在这里
}
编辑:
除此之外,您可能必须使用宏来删除详细信息:
#define WIMPL Window::WindowImpl;
std::unique_ptr<WIMPL> WIMPL::create(){
//implementation goes here
}
定义WIMPL窗口::WindowImpl;
std::unique_ptr WIMPL::create(){
//实现就在这里
}
为什么不简单地创建一个包含
WindowImpl
的名称空间,并将其放在类Window
之外呢?同样,如果不包含“WindowImpl.h”,您肯定无法拥有一个实例Window
。它会因为找不到WindowImpl
@ALX23z的析构函数而尖叫。是的,您可以实例化它,而不包括WindowImpl.h。什么使你认为你不能?因为不包括“WindowImpl.h”编译器将不知道如何删除它。隐马尔可夫模型。。。如果只在Window.cpp中调用了WindowImpl
的析构函数,那么就可以了。@ALX23z编译器需要知道如何在Window的析构函数中删除,WindowImpl是一个完整的类型。我对它进行了测试,它只适用于include Window.h。但是您意识到,现在您必须在Window.cpp内部为Window
实现移动赋值/ctor,这将使其速度变慢且不可内联?这将导致编译器错误“无法使用最新版本的msvc访问在类“Window”中声明的私有类”。@Eric Yes,你说得对,我忘了。我用另一种可能的解决方案编辑了这篇文章。