C++ PImpl习惯用法,在单独的源文件中使用std::unique_指针和实现类

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;

我正在编写一个简单的库来处理跨不同平台的窗口创建。为了抽象出特定于平台的代码,我想使用带有std::unique\u ptr的PImpl习惯用法,并提供一个带有工厂函数的特定于平台的私有实现。这就是我目前拥有的:

Window.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>();
}
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,你说得对,我忘了。我用另一种可能的解决方案编辑了这篇文章。