Cast auto_ptr< Base> to auto_ptr< Derived> [英] Cast auto_ptr<Base> to auto_ptr<Derived>

查看:216
本文介绍了Cast auto_ptr< Base> to auto_ptr< Derived>的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请帮助我理解以下问题。



查看下面的代码示例:

  #include< iostream> 

class Shape {
public:
virtual wchar_t * GetName(){return LShape; }
};
class Circle:public Shape {
public:
wchar_t * GetName(){return LCircle; }
double GetRadius(){return 100 .; }
};

int wmain(){
using namespace std;

auto_ptr< Shape>如;
auto_ptr< Circle> aC(new Circle);

aS = aC;
wcout<< aS-> GetName()<< L'\t'< static_cast< auto_ptr< Circle>>(aS) - > GetRadius()< endl;

return 0;
}

为什么我不允许这样做:

  static_cast< auto_ptr< Circle>>(aS) - > GetRadius()

编译器(MSVCPP 11):

  1> c:\ program文件(x86)\microsoft visual studio 11.0 \vc\include\xmemory(911):错误C2440:'initializing':无法从'Shape *'转换为'Circle *'
1&从基础转换为派生要求dynamic_cast或static_cast


解决方案

auto_ptr 在这方面的行为与指针不同。在时,语言中有特殊规则允许 Shape * 为static_cast到 Circle * Circle 源自 Shape 。 downcast不是完全类型安全的,因为它依赖于用户提供一个实际指向 Shape 的基类类子对象的指针值 Circle ,但标准允许它为方便。 auto_ptr 是只是一个库类,并且没有等价的转换。



即使你能做到,它会经常出错。当您复制 auto_ptr 时,原始文件将丢失资源的所有权。您的 static_cast 会将 auto_ptr 复制到一个临时文件,因此 aS 将被重置,并且当临时表达式(在表达式的结尾处)时资源将被销毁。在你的例子中,很好,因为它会被销毁在返回反正,但一般来说,你不想复制 auto_ptr 除了在函数调用参数或返回值,表示所有权从调用者到被调用者的转移,或反之亦然。



c $ c> static_cast< Circle *>(aS.get()) - > GetRadius(),或者更好地重构代码以避免需要向下转换。如果你知道你的对象是一个 Circle ,保存在 auto_ptr< Circle> [*]。如果你把它保存在 auto_ptr< Shape> ,那么不要依赖它是一个 Circle p>

[*]或者,如果你的实现提供了它们,一个更聪明的指针,如 unique_ptr scoped_ptr shared_ptr 。即使您的实现未提供它们,也有Boost。


Please help me to understand the following issue.

Look at the code example below:

#include <iostream>

class Shape {
public:
  virtual wchar_t *GetName() { return L"Shape"; }
};
class Circle: public Shape {
public:
  wchar_t *GetName() { return L"Circle"; }
  double GetRadius() { return 100.; }
};

int wmain() {
  using namespace std;

  auto_ptr<Shape> aS;
  auto_ptr<Circle> aC(new Circle);

  aS = aC;
  wcout << aS->GetName() << L'\t' << static_cast<auto_ptr<Circle>>(aS)->GetRadius() << endl;

  return 0;
}

Why I am not allowed to do this:

static_cast<auto_ptr<Circle>>(aS)->GetRadius()

Compiler (MSVCPP 11):

1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory(911): error C2440: 'initializing' : cannot convert from 'Shape *' to 'Circle *'
1>          Cast from base to derived requires dynamic_cast or static_cast

解决方案

auto_ptr doesn't behave the same way as a pointer in this respect. There are special rules in the language to allow Shape* to be static_cast to Circle* when Circle derives from Shape. The downcast is not entirely type-safe, since it relies on the user to provide a pointer value that actually does point to the Shape base class sub-object of a Circle, but the standard allows it for convenience. auto_ptr is "just" a library class, and has no equivalent conversion.

Even if you could do it, it would often go wrong. When you copy an auto_ptr, the original loses ownership of the resource. Your static_cast would copy the auto_ptr to a temporary, and so aS would be reset and the resource would be destroyed when the temporary is (at the end of the expression). In your example that's fine, since it's going to be destroyed at return anyway, but generally speaking you don't want to copy auto_ptr except at a function call parameter or return value, to indicate transfer of ownership from caller to callee, or vice versa.

What you can do instead is static_cast<Circle*>(aS.get())->GetRadius(), or better yet restructure your code to avoid the need for a downcast. If you know that your object is a Circle, keep it in an auto_ptr<Circle>[*]. If you keep it in an auto_ptr<Shape>, then don't rely on it being a Circle.

[*] Or, if your implementation provides them, a better smart pointer such as unique_ptr, scoped_ptr or shared_ptr. Even if your implementation doesn't provide them, there's Boost.

这篇关于Cast auto_ptr&lt; Base&gt; to auto_ptr&lt; Derived&gt;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆