首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++ -在初始化类成员之前运行一个函数

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

Stack Overflow用户
提问于 2012-11-09 15:43:08
回答 8查看 9.3K关注 0票数 28

我有两个资源管理类DeviceContextOpenGLContext都是class DisplayOpenGL的成员。资源生存期与DisplayOpenGL相关联。初始化如下(伪代码):

代码语言:javascript
复制
DeviceContext m_device = DeviceContext(hwnd);
m_device.SetPixelFormat();
OpenGLContext m_opengl = OpenGLContext(m_device);

问题是对SetPixelFormat()的调用,因为在DisplayOpenGL c‘’tor的初始化程序列表中不能这样做:

代码语言:javascript
复制
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;
};

我能看到的解决办法:

  • 插入m_dummy(m_device.SetPixelFormat()) -将不能工作,因为SetPixelFormat()没有retval。(你应该这样做吗?)
  • 使用unique_ptr<OpenGLContext> m_opengl;而不是OpenGLContext m_opengl;。 然后初始化为m_opengl(),在c‘’tor主体中调用SetPixelFormat()并使用m_opengl.reset(new OpenGLContext);
  • SetPixelFormat() C‘’tor调用DeviceContext

这些解决方案中哪一种更可取,为什么?我遗漏了什么吗?

如果重要的话,我在Windows上使用VisualStudio2010Express。

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

  • m_dummy()不工作,而且看起来很不雅致,即使它会
  • unique_ptr<X>对我来说很有趣--我什么时候才能用它来代替“普通”X m_x成员呢?除了初始化问题之外,这两种方法在功能上似乎或多或少是等价的。
  • SetPixelFormat()‘tor打电话给DeviceContext当然有效,但我觉得不干净。DeviceContext应该管理资源并启用它的使用,而不是向用户强加一些随机像素格式的策略。
  • 斯蒂金氏 InitDev()看起来是最干净的解决方案。

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

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2012-11-09 19:18:57

逗号接线员去救援!表达式(a, b)将首先计算a,然后计算b

代码语言:javascript
复制
class DisplayOpenGL {
public:
    DisplayOpenGL(HWND hwnd)
    : m_device(hwnd),
      m_opengl((m_device.SetPixelFormat(), m_device)) { };
private:
    DeviceContext m_device;
    OpenGLContext m_opengl;
};
票数 35
EN

Stack Overflow用户

发布于 2012-11-09 20:55:02

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

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

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

方法A:

干净的方式。

m_device的存储创建一个小容器对象,在构造函数中调用SetPixelFormat()。然后用该类型的实例替换DisplayOpenGL ::m_device。获得初始化顺序,目的非常清楚。插图:

代码语言:javascript
复制
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;
};

方法B:

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

代码语言:javascript
复制
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;
};
票数 8
EN

Stack Overflow用户

发布于 2012-11-10 06:10:45

首先,你做错了。永远不会。使那些必须传递给构造函数的助手对象上的操作函数。最好是在类之外构造复杂的对象,并将它们完全创建,这样,如果需要将它们传递给其他类,也可以同时将它们传递到它们的构造函数中。另外,这样您就有机会检测错误,添加合理的日志,等等。

代码语言:javascript
复制
class OpenGLInitialization
{
public:
    OpenGLInitialization(HWND hwnd)
        : mDevice(hwnd) {}
    void                 SetPixelFormat  (void)       { mDevice.SetPixelFormat(); }
    DeviceContext const &GetDeviceContext(void) const { return mDevice; }
private:
    DeviceContext mDevice;
};        

class DisplayOpenGL 
{
public:
    DisplayOpenGL(OpenGLInitialization const &ogli)
    : mOGLI(ogli),
      mOpenGL(ogli.GetDeviceContext())
      {}
private:
    OpenGLInitialization mOGLI;
    OpenGLContext mOpenGL;
};
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13311184

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档