C++ C++;两阶段初始化

C++ C++;两阶段初始化,c++,initialization,unique-ptr,C++,Initialization,Unique Ptr,我正在编写一个使用两阶段初始化的程序。它位于本机GUI API(目前为Win32)之上,并向用户隐藏其复杂性 Windows对C++类的映射通常需要两个阶段的初始化:第一个阶段创建C++对象,第二个阶段创建API对象。 这是必需的,因为订阅窗口事件的第一个机会是在构造函数内部。因此,若您的基本构造函数在订阅事件之前已经创建了窗口,那个么您将错过一些。除此之外,不应该从C++中的构造函数调用虚拟函数,所以它没有办法。 我希望使用以下模式来确保Windows资源(窗口、GDI句柄等)的两阶段初始化

我正在编写一个使用两阶段初始化的程序。它位于本机GUI API(目前为Win32)之上,并向用户隐藏其复杂性

Windows对C++类的映射通常需要两个阶段的初始化:第一个阶段创建C++对象,第二个阶段创建API对象。 这是必需的,因为订阅窗口事件的第一个机会是在构造函数内部。因此,若您的基本构造函数在订阅事件之前已经创建了窗口,那个么您将错过一些。除此之外,不应该从C++中的构造函数调用虚拟函数,所以它没有办法。 我希望使用以下模式来确保Windows资源(窗口、GDI句柄等)的两阶段初始化:

所有使用资源的函数都有create()和destroy()成员函数,它们派生自基模板类

template <class T>
class resource {
public:
    virtual T* create()=0;
    virtual void destroy()=0;
}
模板
类资源{
公众:
虚拟T*create()=0;
虚空销毁()=0;
}
然后,我可以由此派生类:

class wnd : resource<wnd> {
    // do the magic
}
class-wnd:resource{
//施展魔法
}
要创建这些类,我想创建一个全局库函数,它可以执行以下操作:

template <class T, typename... A>
// TODO: Need a concept here, but not available yet.
static std::unique_ptr<T> create(A... args)
{
    T* ptr = new T(args...);
    ptr->create();
    return std::unique_ptr<T>(ptr);
}
模板
//TODO:这里需要一个概念,但还不可用。
静态std::unique_ptr create(A…args)
{
T*ptr=新的T(参数…);
ptr->create();
返回std::unique_ptr(ptr);
}
因此,我会像
auto-button=::create(ctor-args)
那样调用它,它会依次将参数传递给ctor,将unique_ptr返回给我的按钮,并对其调用create函数

现在我也想实施破坏。它将作为自定义删除程序附加到unique_ptr,并将调用destroy()。这就是我——理论上——认为它应该起作用的方式

// --- two phase construction pattern ---
template <typename T>
struct destroy {
    void operator()(T* p) { p->destroy(); delete p; }
};

template <class T, typename... A>
static std::unique_ptr<T> create(A... args)
{
    T* ptr = new T(args...);
    ptr->create();
    return std::unique_ptr<T, destroy<T>>(ptr);
}
/---两阶段施工模式---
模板
结构破坏{
void操作符()(T*p){p->destroy();delete p;}
};
模板
静态std::unique_ptr create(A…args)
{
T*ptr=新的T(参数…);
ptr->create();
返回std::unique_ptr(ptr);
}
问题是,这会失败,因为std::unique\u ptr不能转换为std::unique\u ptr您可以编写一个“holder”类,负责创建对象、初始化对象、完成对象并销毁对象

#include <iostream>
#include <memory>

template<class base>
class holder {
public:
    template<class T, class... Args>
    static holder createAndInitialize(Args... args) {
      holder h = create<T, Args...>(args...);
      h.initialize();
      return h;
    }
    // to create but not initialize
    template<class T, class... Args>
    static holder create(Args... args) {
      return holder(new T(args...));
    }
    void initialize() {
      if (!m_initialized)
      {
        mres->initialize();
        m_initialized = true;
      }
    }
    void finalize()
    {
      if (m_initialized) {
        mres->finalize();
        m_initialized = false;
      }
    }
    // access to the underlying pointer
    const base *ptr() const {
        return mres.get();
    }
    base *ptr() {
        return mres.get();
    }
    ~holder() {
      finalize();
      std::cout << "holder destructor" << std::endl;
    }
private:
    holder(base * res)
      : mres(res), m_initialized(false)
      { }
    holder(holder &&rhs)
    : mres(std::move(rhs.mres)),
      m_initialized(rhs.m_initialized)
      { }
    std::unique_ptr<base> mres;
    bool m_initialized;
};

class resource {
private: // Make these private so that clients cannot invoke directly
    virtual void initialize()=0;
    virtual void finalize()=0;
    
 public:
    virtual ~resource() {}
    virtual void doSomething()=0;
    friend class holder<resource>;
};

class wnd : public resource {
    
public:
    void initialize() override {
        std::cout << "in wnd " << mv << " initialize" << std::endl;
    }
    void finalize() override {
        std::cout << "in wnd " << mv << " finalize" << std::endl;
    }
    void doSomething() override {
        std::cout << "in wnd " << mv << " doSomething" << std::endl;
    }
    ~wnd() {
        std::cout << "in wnd " << mv << " destructor" << std::endl;
    }
private:
    wnd(int v)// make constructor private
      : mv(v)
    {
        std::cout << "in wnd " << v << " constructor" << std::endl;
    }
    
    friend class holder<resource>; // add holder as friend
    int mv;
};

// class which has some child resources
class wnd2 : public resource {
    
public:
    // initialize the child objects
    void initialize() override {
        std::cout << "in wnd2 initialize" << std::endl;
        mres1.initialize();
        mres2.initialize();
    }
    // finalize the child objects
    void finalize() override {
        mres1.finalize();
        mres2.finalize();
        std::cout << "in wnd2 finalize" << std::endl;
    }
    void doSomething() override {
        std::cout << "in wnd2 doSomething" << std::endl;
    }
    ~wnd2() {
      std::cout << "wnd2 destructor" << std::endl;
    }
private:
    // In the constructor, the child objects are only created and not initialized
    wnd2()
      : mres1(holder<resource>::create<wnd>(1)),
        mres2(holder<resource>::create<wnd>(2))
      { }
      
    holder<resource> mres1;
    holder<resource> mres2;
    friend class holder<resource>; // add holder as friend
};

int main()
{
  holder<resource> h2 = holder<resource>::createAndInitialize<wnd2>();
  h2.ptr()->doSomething();
}
#包括
#包括
模板
阶级持有者{
公众:
模板
静态保持架创建和初始化(Args…Args){
保持器h=创建(参数…);
h、 初始化();
返回h;
}
//创建但不初始化
模板
静态保持架创建(Args…Args){
报税表持有人(新T(参数…);
}
void initialize(){
如果(!m_已初始化)
{
mres->initialize();
m_initialized=true;
}
}
void finalize()
{
如果(m_已初始化){
mres->finalize();
m_initialized=false;
}
}
//对底层指针的访问
常数基*ptr()常数{
返回mres.get();
}
基本*ptr(){
返回mres.get();
}
~holder(){
定稿();
标准::cout