【问题标题】:Cannot throw a CException derived exception?不能抛出 CException 派生异常?
【发布时间】:2019-12-16 06:33:32
【问题描述】:

catch exception by pointer in C++看到,据说是按值抛出异常,按引用捕获。

因此,我写了以下代码:

class CMyException : public CException
{
};

void CTestExceptionDlg::OnBnClickedButton1()
{
    // TODO: Add your control notification handler code here
    throw CMyException();
}

但是,这会导致编译器错误:

1>TestExceptionDlg.cpp
1>d:\program files (x86)\microsoft visual studio 9.0\vc\atlmfc\include\afx.h(763) : error C2248: 'CObject::CObject' : cannot access private member declared in class 'CObject'
1>        d:\program files (x86)\microsoft visual studio 9.0\vc\atlmfc\include\afx.h(561) : see declaration of 'CObject::CObject'
1>        d:\program files (x86)\microsoft visual studio 9.0\vc\atlmfc\include\afx.h(532) : see declaration of 'CObject'
1>        This diagnostic occurred in the compiler generated function 'CException::CException(const CException &)'

但是,如果我修改代码以引发新的异常,如下所示:

class CMyException : public CException
{
};

void CTestExceptionDlg::OnBnClickedButton1()
{
    // TODO: Add your control notification handler code here
    throw new CMyException();
}

然后错误就会消失。

为什么?这似乎违反了应该按值抛出异常而不是从堆中分配它的策略?

更新:

下面是CException的声明:

class AFX_NOVTABLE CException : public CObject
{
    // abstract class for dynamic type checking
    DECLARE_DYNAMIC(CException)

public:
// Constructors
    CException();   // sets m_bAutoDelete = TRUE
    explicit CException(BOOL bAutoDelete);   // sets m_bAutoDelete = bAutoDelete

// Operations
    void Delete();  // use to delete exception in 'catch' block

    virtual BOOL GetErrorMessage(_Out_z_cap_(nMaxError) LPTSTR lpszError, _In_ UINT nMaxError,
        _Out_opt_ PUINT pnHelpContext = NULL) const ;
    virtual BOOL GetErrorMessage(_Out_z_cap_(nMaxError) LPTSTR lpszError, _In_ UINT nMaxError,
        _Out_opt_ PUINT pnHelpContext = NULL);
    virtual int ReportError(UINT nType = MB_OK, UINT nMessageID = 0);

// Implementation (setting m_bAutoDelete to FALSE is advanced)
public:
    virtual ~CException() = 0;
    BOOL m_bAutoDelete;
#ifdef _DEBUG
    void PASCAL operator delete(void* pbData);
#if _MSC_VER >= 1200
    void PASCAL operator delete(void* pbData, LPCSTR lpszFileName, int nLine);
#endif
protected:
    BOOL m_bReadyForDelete;
#endif
};

下面是CObject的声明:

class AFX_NOVTABLE CObject
{
public:

// Object model (types, destruction, allocation)
    virtual CRuntimeClass* GetRuntimeClass() const;
    virtual ~CObject() = 0;  // virtual destructors are necessary

    // Diagnostic allocations
    void* PASCAL operator new(size_t nSize);
    void* PASCAL operator new(size_t, void* p);
    void PASCAL operator delete(void* p);
#if _MSC_VER >= 1200
    void PASCAL operator delete(void* p, void* pPlace);
#endif

#if defined(_DEBUG) && !defined(_AFX_NO_DEBUG_CRT)
    // for file name/line number tracking using DEBUG_NEW
    void* PASCAL operator new(size_t nSize, LPCSTR lpszFileName, int nLine);
#if _MSC_VER >= 1200
    void PASCAL operator delete(void *p, LPCSTR lpszFileName, int nLine);
#endif
#endif

    // Disable the copy constructor and assignment by default so you will get
    //   compiler errors instead of unexpected behaviour if you pass objects
    //   by value or assign objects.
protected:
    CObject();
private:
    CObject(const CObject& objectSrc);              // no implementation
    void operator=(const CObject& objectSrc);       // no implementation

// Attributes
public:
    BOOL IsSerializable() const;
    BOOL IsKindOf(const CRuntimeClass* pClass) const;

// Overridables
    virtual void Serialize(CArchive& ar);

#if defined(_DEBUG) || defined(_AFXDLL)
    // Diagnostic Support
    virtual void AssertValid() const;
    virtual void Dump(CDumpContext& dc) const;
#endif

// Implementation
public:
    static const CRuntimeClass classCObject;
#ifdef _AFXDLL
    static CRuntimeClass* PASCAL _GetBaseClass();
    static CRuntimeClass* PASCAL GetThisClass();
#endif
};

【问题讨论】:

  • 能不能显示CObject的减速。似乎编译器无法在CException 的复制构造函数中复制CObject
  • @MRB,我已经包含了 CObject 和 CException 的声明。谢谢。

标签: c++ exception


【解决方案1】:

标准要求被抛出的对象(如果是类类型)必须具有可访问的复制/移动构造函数see this question

所以这个CException 类以及从它派生的任何东西都不能被抛出。如果您可以修改它,则停止从 CObject 派生(这是不可复制的)。或者如果它是系统头文件的一部分,那么它不适合这个目的;您可以改用std::exception 层次结构。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-27
    • 2016-12-17
    • 2012-10-24
    • 1970-01-01
    • 2012-01-24
    • 2013-05-24
    • 2015-07-18
    相关资源
    最近更新 更多