现在的位置: 首页 > 综合 > 正文

C++异常处理的几点注意事项

2013年11月01日 ⁄ 综合 ⁄ 共 3356字 ⁄ 字号 评论关闭

        昨晚又纠结于我的异常处理模块,由于一直考虑DLL的封装性,采用接口方式导出异常管理器,再调用异常管理器的函数成员来创建异常对象,由于返回的是异常对象的接口指针,结果引出了新问题,创建的对象无法在抛出异常时被自动析构。郁闷中只好改变创建异常对象的方法。经过几次血的教训下得出了下面几点注意事项:

1、在异常作用域内,被new出来的对象(变量)在抛出异常时不会被自动析构(释放),所以在抛出异常前要手动将其析构掉(释放)。
2、catch到的对象(变量)只是被throw的对象的一个拷贝副本,抛出异常之后原对象被自动析构(释放)。
3、当throw对象(变量)的指针,拷贝的只是指针变量本身,而不是其所指的对象。如果在catch前,指针所指的对象(变量)已经在异常作用域内被析构(释放),那么在catch时访问指针所指的对象(变量)将会出错。

4、当throw对象(变量)的引用,拷贝的是引用的对象,而不只是拷贝引用名称。
5、catch对象时,应该先catch子类对象后catch父类对象,否则子类对象会先在catch父类对象时被捕获,而catch子类对象时将捕获不到它。

以上几点注意事项可以通过运行下面的代码得到验证:

#include <iostream>
using namespace std;

/* 基类接口 */
class IBase
{
public:
    virtual ~IBase(void)
    {}
 
    virtual void speak(void) = 0;
};

/* 基类 */
class CBase:public IBase
{
public:
    CBase(void)
    {
          cout << "CBase Construction !" << endl;
     }
 
 virtual ~CBase(void)
    {
        cout << "CBase Destruction !" << endl;
    }
 
    virtual void speak(void)
    {
        cout << "I am CBase's Object !" << endl;
    }
};

/* 派生类 */
class CDerive:public CBase
{
public:
    CDerive(void)
    {
        cout << "CDerive Construction !" << endl;
    }
 
    ~CDerive(void)
    {
        cout << "CDerive Destruction !" << endl;
    }
 
    void speak(void)
    {
        cout << "I am CDrive's Object !" << endl;
    }
};

/* 异常测试函数,用于抛出各种类型的对象 */
void ExceptionTest(int i)
{
    switch (i)
    {
        case 1:
        {
            cout << "--IBase * pobjIB = new CBase--" << endl;
            IBase * pobjIB = new CBase;
            throw(pobjIB);
            break;
        }
        case 2:
        {
            cout << "--IBase * pobjIB = new CDerive--" << endl;
            IBase * pobjIB = new CDerive;
            throw(pobjIB);
            break;
        }
        case 3:
        {
            cout << "--CBase * pobjCB = new CBase--" << endl;
            CBase * pobjCB = new CBase;
            throw(pobjCB);
            break;
        }
        case 4:
        {
            cout << "--CBase * pobjCB = new CDerive--" << endl;
            CBase * pobjCB = new CDerive;
            throw(pobjCB);
            break;
        }
        case 5:
        {
            cout << "--CDerive * pobjCD = new CDerive--" << endl;
            CDerive * pobjCD = new CDerive;
            throw(pobjCD);
            break;
        }
        case 6:
        {
            cout << "--CBase & objrCB = objCB--" << endl;
            CBase objCB;
            CBase & objrCB = objCB;
            throw(objrCB);
            break;
        }
        case 7:
        {
            cout << "--CBase & objrCB = objCD--" << endl;
            CDerive objCD;
            CBase & objrCB = objCD;
            throw(objrCB);
            break;
        }
        case 8:
        {
            cout << "--CBase & objrCB = objCD--" << endl;
            CDerive objCD;
            CDerive & objrCD = objCD;
            throw(objrCD);
        }
        case 9:
        {
            cout << "--CBase objCB--" << endl;
            CBase objCB;
            throw(objCB);
            break;
        }
        case 10:
        {
            cout << "--CDerive objCD;--" << endl;
            CDerive objCD;
            throw(objCD);
            break;
        }
    }
};

int main(void)
{
    try
    {
        ExceptionTest(7); 
    }
    catch(CDerive * pobjCD)
    {
        cout << "==catch(CDerive * bobjCD)==" << endl;
        pobjCD->speak();
    }
    catch(CBase * pobjCB)
    {
        cout << "==catch(CBase * pobjCB)==" << endl;
        pobjCB->speak();
    }
    catch(IBase * pobjIB)
    {
        cout << "==catch(IBase * pobjIB)==" << endl;
        pobjIB->speak();  
    }
    catch(CDerive objCD)
    {
        cout << "==catch(CDerive objCD)==" << endl;
        objCD.speak();
    }
    catch(CBase objCB)
    {
        cout << "==catch(CBase objCB)==" << endl;
        objCB.speak();
    }
    catch(...)
    {
        cout << "catch(...)" << endl;
    }
    return 0;
};

抱歉!评论已关闭.