Christian Aichinger Christian Aichinger - 3 days ago 5
C++ Question

C++ - Run a function before initializing a class member

I have 2 resource managing classes

DeviceContext
and
OpenGLContext
both are members of
class DisplayOpenGL
. The resource lifetimes are tied to
DisplayOpenGL
. Initialization looks like this (pseudo code):

DeviceContext m_device = DeviceContext(hwnd);
m_device.SetPixelFormat();
OpenGLContext m_opengl = OpenGLContext(m_device);


The problem is the call to SetPixelFormat(), since I can't do that in the initializer list of the
DisplayOpenGL
c'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;
};


Solutions that I can see:


  • Inserting
    m_dummy(m_device.SetPixelFormat())
    - Won't work as SetPixelFormat() has no retval. (should you do this if it had a retval?)

  • Use
    unique_ptr<OpenGLContext> m_opengl;
    instead of
    OpenGLContext m_opengl;
    .

    Then initialize as
    m_opengl()
    , call SetPixelFormat() in the c'tor body and use
    m_opengl.reset(new OpenGLContext);

  • Call
    SetPixelFormat()
    from
    DeviceContext
    c'tor



Which of these solutions is preferable and why? Anything I am missing?

I'm using Visual Studio 2010 Express on Windows, if it matters.

Edit: I'm mostly interested in the tradeoffs involved in deciding for one of these methods.


  • m_dummy()
    doesn't work and seems inelegant even if it would

  • unique_ptr<X>
    is interesting to me - when would I use it instead of a "normal"
    X m_x
    member? The two methods seem to be functionally more or less equivalent, except for the initialization issues.

  • Calling
    SetPixelFormat()
    from
    DeviceContext
    c'tor certainly works but feels unclean to me.
    DeviceContext
    should manage the resource and enable its use, not impose some random pixel format policy on users.

  • stijn's
    InitDev()
    looks like the cleanest solution.



Do I pretty much always want a smart pointer based solution in such cases anyway?

MSN MSN
Answer

Comma operator to the rescue! An expression (a, b) will evaluate a first, then b.

class DisplayOpenGL {
public:
    DisplayOpenGL(HWND hwnd)
    : m_device(hwnd),
      m_opengl((m_device.SetPixelFormat(), m_device)) { };
private:
    DeviceContext m_device;
    OpenGLContext m_opengl;
};
Comments