Cast auto_ptr< Base> to auto_ptr< Derived> [英] 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< Base> to auto_ptr< Derived>的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!