正文

第12集 C++的异常对象按指针方式被传递2006-01-21 11:37:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/mroske/9768.html

分享到:

  上两篇文章分别详细讨论了C++的异常对象按值传递和按引用传递的两种方式,本文继续讨论最后的一种的方式:按指针传递。

异常对象在什么时候构造?

  1、与按值和按引用传递异常的方式相比,在按指针传递异常的方式下,异常对象的构造方式有很大的不同。它必须是在堆中动态构造的异常对象,或者是全局性static的变量。示例程序如下:

void main()
{
try
{
// 动态在堆中构造的异常对象
throw new MyMemoryException("ex_obj1");
}
catch(MyException* e)
{
cout<<endl<<"捕获到一个MyException*类型的异常,名称为:"<<e->GetName()<<endl;

delete e;
}
}

  2、注意,通过指针方式传递的异常对象不能是局部变量,否则后果很严重,示例如下:

void main()
{
try
{
// 局部变量,异常对象
MyMemoryException ex_obj1("ex_obj1");

// 抛出一个指针类型的异常
// 注意:这样做很危险,因为ex_obj1这个对象离开了这个作用域即
// 析构销毁
throw &ex_obj1;
}
catch(MyException* e)
{
// 下面语句虽然不会导致程序崩溃,但是e->GetName()取得的结果
// 也是不对的。
cout<<endl<<"捕获到一个MyException*类型的异常,名称为:"<<e->GetName()<<endl;

// 这条语句会导致程序崩溃
// delete e;
}
}

  程序运行的结果是:
  构造一个MyException异常对象,名称为:ex_obj1
  构造一个MyMemoryException异常对象,名称为:ex_obj1
  销毁一个MyMemoryException异常对象,名称为:ex_obj1
  销毁一个MyException异常对象,名称为:ex_obj1

  捕获到一个MyException*类型的异常,名称为:
  异常对象按指针方式被传递
  指针是历史悠久的一种数据类型形式,这可以追溯到C语言和PASCAL语言中。异常对象按指针方式传递,当然更是不会发生对象的拷贝复制过程。所以这种方式传递异常对象是效率最高的,它从抛出异常、捕获异常再到异常错误处理结束过程中,总共只会发生唯一的一次对象的构造过程,那就是异常对象最初在堆中的动态创建时的初始化的构造过程。也看看示例程序吧!如下:

void main()
{
try
{
// 动态在堆中构造的异常对象
throw new MyMemoryException("ex_obj1");
}
// 注意:这里是定义了按指针方式传递异常对象
catch(MyException* e)
{
cout<<endl<<"捕获到一个MyException*类型的异常,名称为:"<<e->GetName()<<endl;

delete e;
}
}

  程序运行的结果是:
  构造一个MyException异常对象,名称为:ex_obj1
  构造一个MyMemoryException异常对象,名称为:ex_obj1

  捕获到一个MyException*类型的异常,名称为:ex_obj1
  销毁一个MyMemoryException异常对象,名称为:ex_obj1
  销毁一个MyException异常对象,名称为:ex_obj1

  呵呵!程序的运行结果是不是显示出异常对象只有一次的构造过程。挺好挺好!

异常对象什么时候被销毁

  异常对象动态地在堆上被创建,同时它也要动态的被销毁,否则就必然会发生内存泄漏。那么异常对象应该在什么时候被销毁比较合适呢?当然应该是在catch block块中处理完毕后再销毁它才比较合理。示例如下:

void main()
{
try
{
// 动态在堆中构造的异常对象
throw new MyMemoryException("ex_obj1");
}
catch(MyException* e)
{
cout<<endl<<"捕获到一个MyException*类型的异常,名称为:"<<e->GetName()<<endl;

// 这里需要显示的删除异常对象
delete e;
}
}

  指针方式下,异常对象会发生对象切片吗?
  当然不会,试都不用试,阿愚非常有把握确信这一点。

总结

  (1) 被抛出的异常对象不能是局部变量或临时变量,必须是在堆中动态构造的异常对象,或者是全局性static的变量;
  (2) 异常对象只会被构造一次;
  (3) catch 后面带的异常对象的作用域仅限于catch bock中;
  (4) 异常对象动态地在堆上被创建,同时它也要动态的被销毁。

  至此为止,C++的异常对象的传递的三种方式(指针、传值和引用)都已经讨论过了,主人公阿愚到此算是松了一大口气,终于把这块比较难肯一点的骨头给拿下了(呵呵!^_^)。为了更进一步巩固这些知识。下一篇文章准备对这三种方式来一个综合性的大比较!去看看吧!

阅读(3098) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册