代码之家  ›  专栏  ›  技术社区  ›  Baiyan Huang

为什么禁用CObject的复制构造函数和赋值

  •  8
  • Baiyan Huang  · 技术社区  · 15 年前

    构造函数按成员进行构造 收到。私人的存在 CObject复制构造函数保证 如果副本 需要类的构造函数 但不可用。因此你必须 类需要此功能。

    禁用复制构造函数并

    我的问题是,这个CObject类的默认逐位复制构造函数有什么问题?在我看来,最好给我们一个默认的拷贝构造函数,如果需要的话,我们可以提供一个(deep copy)

    2 回复  |  直到 15 年前
        1
  •  6
  •   peterchen    15 年前

    e、 g.CGD对象大致为:

    class CGDIObject : public CObject
    {
        HGDIOBJ m_handle;
    
        CGDIObject() : m_handle(0) {}
        // derived classes provide a create, attach etc.
       ~CGDIObject() { DeleteObject(m_handle); } 
    }
    

    这里的默认复制构造函数是危险的(导致双重破坏),提供一个“正确”的复制构造函数是非常困难和昂贵的。

    另一个原因可能是,大多数CObject派生类都是经过变异的,因此通过引用传递。缺少的副本构造函数将捕获意外的副本,这些副本会改变副本而不是传递的对象:

    class CMyObject : public CObject
    {
       public:
          AttachFoo(FooHandle foo) { ... }
          AddBar() { ... }
    };
    
    bool InitMySession(CMyObject & obj)
    {
        obj.AttachFoo(CreateRawFoo());   
        obj.AddBar();
        obj.AddBar();
    }
    
    // ...
    CMyObj mo;
    InitMySession(mo);
    

    mo 保持不变。

    相当多的API遵循这种模式,因为MFC不依赖异常来处理错误(由于历史原因:并非所有目标编译器都能很好地支持它们,而且MFC需要大量额外的资源处理,这会让异常变得很痛苦)。


    我不认为这些选择是好的,例如,派生类应该被允许使用默认的复制构造函数,如果他们的成员允许的话(大多数成员应该允许)。

    不过,这一决定符合MFC的“思维模式”,也符合MFC创建时的要求/限制。

        2
  •  3
  •   Billy ONeal IS4    15 年前

    考虑以下几点:

    class CMyHandle : public CObject
    {
        HANDLE hWin32;
    public:
        CMyHandle()
        {
            hWin32 = SomeFunctionThatMakesHandle();
        }
        ~CMyHandle()
        {
            CloseHandle(hWin32);
        }
    };
    

    现在,如果你收到 CMyHandle ,手柄最终关闭两次,在 实例被销毁,另一个实例将变为无效。

    由于大量的MFC类管理句柄,因此强制类的创建者显式重写以创建复制构造函数和复制赋值运算符是有意义的。

    int main()
    {
        CMyHandle h1; //CMyHandle's constructor initializes the handle
        {
            CMyHandle h2(h1); //Memberwise copy into h2. In this case, it copies the
                              //handle
        } //h2 destroyed, closes handle
        //h1 is now invalid (because the underlying handle was closed)!
    }