C++ - 在初始化类成员之前运行一个函数

Chr*_*ger 19 c++ constructor initialization smart-pointers initialization-list

我有2个资源管理类DeviceContext,OpenGLContext都是class DisplayOpenGL.资源生命周期与之相关DisplayOpenGL.初始化看起来像这样(伪代码):

DeviceContext m_device = DeviceContext(hwnd);
m_device.SetPixelFormat();
OpenGLContext m_opengl = OpenGLContext(m_device);
Run Code Online (Sandbox Code Playgroud)

问题是调用SetPixelFormat(),因为我无法在DisplayOpenGLc'tor 的初始化列表中执行此操作:

class DisplayOpenGL {
public:
    DisplayOpenGL(HWND hwnd)
    : m_device(hwnd),
      // <- Must call m_device.SetPixelFormat here ->
      m_opengl(m_device) { };
private:
    DeviceContext m_device;
    OpenGLContext m_opengl;
};
Run Code Online (Sandbox Code Playgroud)

我能看到的解决方案:

  • 插入m_dummy(m_device.SetPixelFormat())- 无法工作,因为SetPixelFormat()没有retval.(如果它有一个retval,你应该这样做吗?)
  • unique_ptr<OpenGLContext> m_opengl;而不是OpenGLContext m_opengl;.
    然后初始化为m_opengl(),在c'tor体中调用SetPixelFormat()并使用m_opengl.reset(new OpenGLContext);
  • SetPixelFormat()来自DeviceContextc'tor的 电话

哪种解决方案更可取?为什么?我错过了什么?

我在Windows上使用Visual Studio 2010 Express,如果重要的话.

编辑:我最感兴趣的是在决定使用其中一种方法时所涉及的权衡.

  • m_dummy() 不工作,即使它会显得不优雅
  • unique_ptr<X>对我来说很有意思 - 我何时会使用它而不是"正常" X m_x成员?除初始化问题外,这两种方法似乎在功能上或多或少相同.
  • 调用SetPixelFormat()DeviceContextc'tor肯定的作品,但感觉不干净的给我.DeviceContext应管理资源并启用其使用,而不是对用户施加一些随机像素格式策略.
  • stijn InitDev()看起来像最干净的解决方案.

在这种情况下,我是否总是想要一个基于智能指针的解决方案呢?

MSN*_*MSN 16

逗号操作员来救援!然后,表达式(a, b)a首先进行评估b.

class DisplayOpenGL {
public:
    DisplayOpenGL(HWND hwnd)
    : m_device(hwnd),
      m_opengl((m_device.SetPixelFormat(), m_device)) { };
private:
    DeviceContext m_device;
    OpenGLContext m_opengl;
};
Run Code Online (Sandbox Code Playgroud)

  • 我想你会做 `m_opengl((m_device.SetPixelFormat(), m_device), arg2)` (2认同)

jus*_*tin 6

在这种情况下,我几乎总是想要一个基于智能指针的解决方案吗?

不。避免这种不必要的并发症。

没有提到的两种直接方法:

方法一:

干净的方式。

为在构造函数m_device中调用的存储创建一个小容器对象SetPixelFormat()。然后用DisplayOpenGL ::m_device该类型的实例替换。得到了初始化顺序,意图很明确。插图:

class DisplayOpenGL {
public:
    DisplayOpenGL(HWND hwnd)
        : m_device(hwnd),
            m_opengl(m_device) { }
private:
    class t_DeviceContext {
    public:
        t_DeviceContext(HWND hwnd) : m_device(hwnd) {
            this->m_device.SetPixelFormat();
        }
        // ...
    private:
        DeviceContext m_device;
    };
private:
    t_DeviceContext m_device;
    OpenGLContext m_opengl;
};
Run Code Online (Sandbox Code Playgroud)

方法B:

快速而肮脏的方式。在这种情况下,您可以使用静态函数:

class DisplayOpenGL {
public:
    DisplayOpenGL(HWND hwnd)
    : m_device(hwnd),
      m_opengl(InitializeDevice(m_device)) { }
private:
    // document why it must happen this way here
    static DeviceContext& InitializeDevice(DeviceContext& pDevice) {
      pDevice.SetPixelFormat();
      return pDevice;
    }
private:
    DeviceContext m_device;
    OpenGLContext m_opengl;
};
Run Code Online (Sandbox Code Playgroud)