智能指针和异常处理

时间:2011-09-05 14:17:40

标签: c++ exception smart-pointers

我已经浏览了互联网,这个帖子正在寻找一个完整的 回答我面临的这种情况。我已经读到了投掷聪明 指向对象的指针不是很聪明。我只想了解原因 这是怎么回事。我会解释一下情况。让我们想象一下 简单的层次结构:

class Foo 
{ 
public: virtual ~Foo() {} 
}; 

typedef tr1::shared_ptr<Foo> SPFoo; 

class FooInherited: public Foo { }; 

typedef tr1::shared_ptr<FooInherited> SPFooInherited; 

让我们检查一下这个测试代码:

int main(int argc, char** argv) 
{ 
  try 
  { 
    throw FooInherited(); 
  } 
  catch(const Foo& f) 
  { 
    cout << "Foo& caught!" << endl; 
  } 
  try 
  { 
    throw SPFooInherited(new FooInherited()); 
  } 
  catch(const SPFoo& f) 
  { 
    cout << "SPFoo& caught!" << endl; 
  } 
  return 0; 
} 

一切都在编译,但在运行时第二次尝试捕获不会 执行。有人能解释一下为什么吗?特别是如果代码行像 这项工作在运行时完美无缺。

void function(const SPFoo& f) 
{ 
} 

... 

SPFooInherited fi(new FooInherited()); 
function(fi);

我确实理解问题是SPFooInherited不从SPFoo继承(即使FooInherited继承自Foo),但它非常想知道什么是编译器/ RTE在捕获异常时与函数调用示例的不同之处不能解决de情况。是因为catch参数与函数调用参数不同吗?为什么Foo&amp;作品和SPFoo没有?

非常感谢您提前。

此致 伊克尔。

2 个答案:

答案 0 :(得分:13)

正如您在问题中所说,SPFooInherited不是SPFoo的子类。这意味着catch(SPFoo const&)将不会捕获SPFooInherited的实例。另一方面,FooInherited继承自Foo,因此catch(Foo const&)将捕获FooInherited的实例。

要理解这一点,您不需要对编译器或运行时环境有任何特殊的了解。它只是语言的一部分。

对函数的调用有效的原因是tr1::shared_ptr有一个模板化的非显式构造函数,允许在函数调用站点进行隐式转换。

即:tr1::shared_ptr具有以下构造函数:

//Note the lack of explicit
template<class Y> shared_ptr(shared_ptr<Y> const & r);

这允许从不同的共享指针类型构造shared_ptr。此构造函数的实现依赖于从FooInherited*Foo*的隐式转换,以将SPFooInherited中的指针实际存储到SPFoo中。如果此隐式转换不存在,则代码将无法编译,因此shared_ptr与不相关类型之间的不安全转换将不会发生。

函数调用和catch之间的根本区别在于隐式转换将在函数参数的初始化中发生,但catch只能匹配单个类型(FooInherited is-a Foo,所以它会匹配)。

答案 1 :(得分:3)

因为SPFoo不是SPFooInherited的子类。 catch块只会捕获其捕获列表中的内容,或者捕获其捕获列表中的内容的公共子类。 FooInherited来自Foo,因此抓住Foo也会让您抓住FooInheritedSPFooSPFooInherited是完全不同且无关的类。