以任何方式将基指针强制转换为派生指针是否危险



我一直避免使用c++类型转换(static_cast, const_cast, dynamic_cast[我也避免使用RTTI]等),因为我认为它们浪费了输入,而且我从未看到任何优点,所以我只使用C风格的类型转换。

我的问题是,如果你有一个继承层次结构和一个指向基类型的指针,你能安全地将基指针强制转换为具有c风格强制转换的派生指针(只要你绝对确定基指针指向派生类型的实例),而不会在幕后发生一些事情,导致看似无法解释的失败吗?

我问这个问题是因为我在另一个问题的评论中读到,使用c风格的从基类型到派生类型的强制转换不会"调整指针"或类似的东西。

使用static_castdynamic_cast进行浇注,有一定的安全性。
如果强制转换无效,static_cast会给你一个编译时错误,
dynamic_cast在运行时抛出引用异常或在无效强制转换的情况下返回空指针。

因此,它们比c风格的强制类型要好,主要是因为它们提供了安全性。

如果你绝对确定强制转换是有效的,即使是c风格的强制转换也会做同样的事情,但最好使用语言提供的安全性,而不是自己管理它(因为我们不需要)。

一个dynamic_cast指向一个指针(不是一个引用)给你一个机会来检测错误并处理它;普通的C型则不会。但是,如果你对类型有绝对的把握,那么c风格的强制转换——尽管很糟糕——应该没问题;

如果你的派生类引入了额外的成员,是的,我认为如果你试图索引指针或指针上的索引作为数组,事情可能会出错。

考虑以下内容:

class base
{
public:
    int _data1;
    base () : _data1(0) {}
};
class derived : public base
{
public:
    int _data2;
    derived () : _data2(1) {}
};
int main ()
{
    base *_base_ptr = new derived[10];
    // this isn't going to work correctly, because the compiler will use `sizeof(base)` 
    // to do the pointer offsets, rather than sizeof(derived)...
    int _data = _base_ptr[1]._data1;
    delete[] _base_ptr;
    return _data;
}

ideone中运行此代码片段返回1,而不是预期的0

c++样式强制转换在模板代码中很重要。在模板代码中,我们不太确定要转换的对象的类型,因为这些类型是由用户提供的。如果你最终做了一个不需要的强制转换(例如不相关指针类型之间的静态强制转换),c++风格的强制转换会给你编译器错误,但C风格的强制转换无论如何都会进行强制转换。

例如(小例子)

template <class T>
T* safe_downcast(Base* ptr)
{
  return static_cast<T*>(ptr);
}

如果我使用C风格强制转换,那么这个函数就不安全了。

但是我同意,在模板代码之外,我经常使用C风格强制转换

如果您绝对确定基类指针实际上指向派生类型的实例,为什么还要使用基类指针呢?另外:这听起来好像是虚函数的经典案例。如果出于某些原因(性能,…),您希望避免虚拟调用,请查找CRTP。

我使用c++风格的强制转换,主要是因为它们提醒我检查强制转换是否绝对必要。如果可能的话,我尽量避免reinterpret_cast和dynamic_cast(大多数时候是这样的),并且我主要在CRTP模板类中使用static_cast,在那里它是OK的。

最新更新