Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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?

like image 922
Christian Aichinger Avatar asked Nov 09 '12 15:11

Christian Aichinger


People also ask

How do you initialize a class member?

To initialize a class member variable, put the initialization code in a static initialization block, as the following section shows. To initialize an instance member variable, put the initialization code in a constructor.

Why initializing a class member variable during declaration is not permitted?

The main reason is that initialization applies to an object, or an instance, and in the declaration in the class there is no object or instance; you don't have that until you start constructing. There's been some evolution in this regard.

Can we initialize data members in a class?

In C++, class variables are initialized in the same order as they appear in the class declaration. Consider the below code. The program prints correct value of x, but some garbage value for y, because y is initialized before x as it appears before in the class declaration.

Can we initialize a class member variable as soon as the same is defined?

No! We cannot initialize a structure members with its declaration, consider the given code (that is incorrect and compiler generates error).


1 Answers

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; }; 
like image 102
MSN Avatar answered Oct 02 '22 02:10

MSN