C++不能中断构造函数来拒绝产生对象(在构造和析构中抛出异常)

时间:2023-03-08 19:49:41

这是我的感觉,具体需要研究一下~

找到一篇文章:在构造和析构中抛出异常

测试验证在类构造和析构中抛出异常, 是否会调用该类析构.

如果在一个类成员函数中抛异常, 可以进入该类的析构函数.

  1. /// @file ClassroomExamples.cpp
  2. /// @brief xxxx-xxxx课堂笔记的验证代码
  3. /// 测试c++异常
  4. /// 在构造和析构中抛出异常
  5. #include <iostream>
  6. #include <limits>
  7. #include "MyException.h"
  8. #include "TestThrow.h"
  9. using namespace std;
  10. void clear_cin();
  11. void fnTest_terminate();
  12. // typedef void (__cdecl *terminate_function)()
  13. void my_terminate_function();
  14. void test_try_catch();
  15. /// 声明接口异常
  16. /// 在函数后面修饰 throw(x, y, z)
  17. /// 说明该函数要抛出哪种异常, 给调用者看的
  18. /// 函数后面的throw修改, 说明本函数要抛出什么类型的异常
  19. /// 但是M$并没有在函数中校验throw的类型是否和函数说明相同
  20. /// throw可以修饰一个函数中抛出的多个异常
  21. void fnOnTryCatch(char* pIn) throw(CMyException*, int);
  22. /// throw() 表明, 该函数保证不抛出任何异常
  23. void fnOnTryCatch1(char* pIn) throw();
  24. int main(int argc, char** argv, char** envp)
  25. {
  26. test_try_catch();
  27. // fnTest_terminate();
  28. cout << "END, press any key to quit" << endl;
  29. clear_cin();
  30. getchar();
  31. return 0;
  32. }
  33. void test_try_catch()
  34. {
  35. char* p = NULL;
  36. /// 如果没有catch能接住异常, 被OS接住后, 直接弹abort框
  37. /// CTestThrow Test1; ///< 模拟没有catch能接住异常的情况
  38. try
  39. {
  40. // 如果Test2的构造中抛出异常, CTestThrow中缺没能catch住异常, Test2的析构不会被调用
  41. CTestThrow Test2;
  42. fnOnTryCatch1(p); ///< 前面抛出了异常, 这句也就不会被执行.
  43. // fnOnTryCatch(p);
  44. }
  45. /// 用基类指针去捕获异常
  46. /// throw的是具体异常子类的指针
  47. catch (IMyExceptionBase* pe)
  48. {
  49. if (NULL != pe)
  50. {
  51. cout << pe->GetErrMsg() << endl;
  52. delete pe;
  53. pe = NULL;
  54. }
  55. }
  56. catch(...)
  57. {
  58. cout << "catch(...)" << endl;
  59. }
  60. }
  61. void fnOnTryCatch1(char* pIn)
  62. {
  63. if (NULL != pIn)
  64. {
  65. /// 但是M$并没有在函数中校验throw的类型是否和函数说明相同
  66. // throw((int)2); ///< M$
  67. *pIn = 'e';
  68. }
  69. }
  70. void fnOnTryCatch(char* pIn)
  71. {
  72. if (NULL == pIn)
  73. {
  74. // throw((int)2);
  75. /// 但是M$并没有在函数中校验throw的类型是否和函数说明相同
  76. // throw((double)3);
  77. throw(new CMyException("fnOnTryCatch (NULL == pIn)"));
  78. }
  79. *pIn = 't';
  80. }
  81. void fnTest_terminate()
  82. {
  83. // terminate(); ///< 调用了 abort
  84. set_terminate(my_terminate_function);
  85. terminate();
  86. }
  87. void my_terminate_function()
  88. {
  89. /// 可以做些收尾的事情
  90. cout << "my_terminate_function()" << endl;
  91. /// 如果不调用 exit, OS会调用abort, 很不体面的弹abort框
  92. exit(0); ///< 这样就不会弹框了
  93. }
  94. void clear_cin()
  95. {
  96. cin.clear();
  97. cin.sync();
  98. }
  1. // MyException.cpp: implementation of the CMyException class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "MyException.h"
  5. //////////////////////////////////////////////////////////////////////
  6. // Construction/Destruction
  7. //////////////////////////////////////////////////////////////////////
  8. CMyException::CMyException(const char* pcErrMsg)
  9. :m_pcErrMsg(pcErrMsg)
  10. {
  11. }
  12. CMyException::~CMyException()
  13. {
  14. }
  15. const char* CMyException::GetErrMsg()
  16. {
  17. return m_pcErrMsg;
  18. }
  1. // MyException.h: interface for the CMyException class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #if !defined(AFX_MYEXCEPTION_H__96603384_DB81_48CE_8173_29BC2A82F26A__INCLUDED_)
  5. #define AFX_MYEXCEPTION_H__96603384_DB81_48CE_8173_29BC2A82F26A__INCLUDED_
  6. #if _MSC_VER > 1000
  7. #pragma once
  8. #endif // _MSC_VER > 1000
  9. #include "MyExceptionBase.h"
  10. class CMyException : public IMyExceptionBase
  11. {
  12. public:
  13. CMyException(const char* pcErrMsg);
  14. virtual ~CMyException();
  15. virtual const char* GetErrMsg(); ///< 接口, 取错误消息
  16. private:
  17. const char* m_pcErrMsg;
  18. };
  19. #endif // !defined(AFX_MYEXCEPTION_H__96603384_DB81_48CE_8173_29BC2A82F26A__INCLUDED_)
  1. // MyExceptionBase.cpp: implementation of the CMyExceptionBase class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "MyExceptionBase.h"
  5. //////////////////////////////////////////////////////////////////////
  6. // Construction/Destruction
  7. //////////////////////////////////////////////////////////////////////
  8. IMyExceptionBase::IMyExceptionBase()
  9. {
  10. }
  11. IMyExceptionBase::~IMyExceptionBase()
  12. {
  13. }
  1. // MyExceptionBase.h: interface for the CMyExceptionBase class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #if !defined(AFX_MYEXCEPTIONBASE_H__90DA9DC6_7686_417F_801B_2DC4F1E7A3C5__INCLUDED_)
  5. #define AFX_MYEXCEPTIONBASE_H__90DA9DC6_7686_417F_801B_2DC4F1E7A3C5__INCLUDED_
  6. #if _MSC_VER > 1000
  7. #pragma once
  8. #endif // _MSC_VER > 1000
  9. class IMyExceptionBase
  10. {
  11. public:
  12. IMyExceptionBase();
  13. virtual ~IMyExceptionBase() = 0;
  14. virtual const char* GetErrMsg() = 0; ///< 接口, 取错误消息
  15. };
  16. #endif // !defined(AFX_MYEXCEPTIONBASE_H__90DA9DC6_7686_417F_801B_2DC4F1E7A3C5__INCLUDED_)
  1. // TestThrow.cpp: implementation of the CTestThrow class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include <stddef.h>
  5. #include <iostream>
  6. using namespace std;
  7. #include "TestThrow.h"
  8. #include "MyException.h"
  9. //////////////////////////////////////////////////////////////////////
  10. // Construction/Destruction
  11. //////////////////////////////////////////////////////////////////////
  12. CTestThrow::CTestThrow()
  13. {
  14. /// 构造函数失败时, 可以抛出异常
  15. /// 假设资源分配失败, 要抛出异常
  16. /// 如果抛出的异常, 没有被我们的catch接住, 被OS接住后, 直接弹abort框
  17. /// 在类中抛出异常后, 如果没有在类中catch住, 就不会自动调用析构.
  18. /// 如果在类中需要抛出异常, 而且本类没有catch能接住该异常,
  19. /// 要先释放能释放的资源, 才能throw异常
  20. /// 必须在构造函数中的try中抛出异常的类
  21. /// 才会在本类生命期结束的时候, 自动析构
  22. /// 如果被其他作用域的catch捕获, 本类的析构不会被调用
  23. throw(new CMyException("failed CTestThrow::CTestThrow()"));
  24. }
  25. CTestThrow::~CTestThrow()
  26. {
  27. /// 析构函数中, 从语法上讲, 是不应该抛出异常的
  28. /// 如果一个类已经在销毁了, 可是有问题, 我们也做不了什么
  29. /// 所以 : 析构函数不应该抛出异常
  30. // throw(new CMyException("failed CTestThrow::~CTestThrow()"));
  31. cout << "CTestThrow::~CTestThrow()" << endl;
  32. }
    1. // TestThrow.h: interface for the CTestThrow class.
    2. //
    3. //////////////////////////////////////////////////////////////////////
    4. #if !defined(AFX_TESTTHROW_H__573ED8BA_B817_440C_9D67_14CBCA9EA6FC__INCLUDED_)
    5. #define AFX_TESTTHROW_H__573ED8BA_B817_440C_9D67_14CBCA9EA6FC__INCLUDED_
    6. #if _MSC_VER > 1000
    7. #pragma once
    8. #endif // _MSC_VER > 1000
    9. class CTestThrow
    10. {
    11. public:
    12. CTestThrow();
    13. virtual ~CTestThrow();
    14. };
    15. #endif // !defined(AFX_TESTTHROW_H__573ED8BA_B817_440C_9D67_14CBCA9EA6FC__INCLUDED_)

http://blog.****.net/lostspeed/article/details/50439069