我已经阅读了一些关于使用C ++进行转换的内容。来自C背景,使用普通(type)
强制转换对void *
之类的内容很常见,但对于C ++,有dynamic_cast
,reinterpret_cast
,static_cast
等。
问题/问题/问题是在基指针和派生指针之间进行转换时应该使用上述哪些转换。
我们的数据存储存储指向基类(B
)的指针。函数分配派生指针(D
)。
代码示例如下:
class B
{ int _some_data; }
class D : public B
{ int _some_more_data; }
然后代码看起来像:
D *obj = new D;
obj->_some_data = 1;
obj->_some_more_data = 2;
<store obj>
然后我们访问数据时:
B *objB = <get out data>
if (objB->_some_data == 1)
{ D *objD = (D *) objB; <do some processing> }
现在我担心的演员是D *objD = (D *) objB
。
我们应该使用哪种演员?
感谢。
答案 0 :(得分:6)
在这种情况下,没有演员表是真正安全的。
最安全的是dynamic_cast
,但您的对象不是多态的,所以它不适用于此处。但你应该考虑至少有一个virtual
析构函数,因为我可以看到你计划扩展类。
static_cast
不安全,正如msdn页面所指出的那样:
class B {};
class D : public B {};
void f(B* pb, D* pd) {
D* pd2 = static_cast<D*>(pb); // not safe, pb may
// point to just B
B* pb2 = static_cast<B*>(pd); // safe conversion
}
reinterpret_cast
也没有检查,所以不要依赖它。
此外,转换为派生类的指针至少是代码气味,如果你需要这样做,99%肯定你有一个有缺陷的设计。
答案 1 :(得分:3)
对于您了解但编译器没有的相关类型,请使用static_cast
。
但在你的情况下,你根本不应该投。
你写的那个
我们的数据存储存储指向基类(B)的指针。函数分配派生指针(D)。
这是丢弃信息,这不是一个好主意。有人意识到这不是一个好主意,实际上它无法工作,因此试图将该类型信息动态保存在B::_some_data
的值中。总效果:抛弃 C ++支持来处理该类型信息,并替换一个非常脆弱和肮脏的本土解决方案。
为了利用C ++支持,使B成为多态类,即至少有一个virtual
成员:
struct B { virtual ~B() {} };
我删除了数据成员_some_data
,因为显然它的唯一目的是跟踪动态类型,现在C ++支持在实践中通过对象中所谓的“vtable指针”来实现。总的对象大小可能是相同的。然而,虫子的吸引力和纯粹的丑陋程度降低了几个数量级。 ; - )
然后,
struct D
: B
{
int some_more_data_;
D( int v ): some_more_data_( v ) {}
};
然后,对于多态类,您的处理代码可以使用安全的 dynamic_cast
,如下所示:
B* const objB = getOutData();
if( D* const objD = dynamic_cast<D*>( objB ) )
{
// do some processing using objD
}
现在,这种手动动态类型检查仍然非常脏,反映了非OO系统架构。使用对象取向,而不是操作检查它们被赋予了什么类型的数据,数据有效地包含指向适当的专门操作的指针。但我认为最好一步一步,作为上面的第一步:摆脱脆弱的虫子 - 吸引本土的动态类型检查方案,并使用相对干净的超级duper新鲜美味的好看等等.C ++支持。 : - )
答案 2 :(得分:0)
在这种情况下,您应该使用dynamic_cast
。