C++ C++;安全的动态_-cast替代方案

C++ C++;安全的动态_-cast替代方案,c++,casting,C++,Casting,在什么情况下可以使用reinterpret\u cast从实际上是派生实例指针的基指针进行强制转换?(通过多态性) 如果继承是多态的,则静态强制转换不起作用 我考虑了这个琐碎的场景: class A { public: virtual void Hello() { cout<<" A "; } virtual int GetType() { return 1; } }; class B: public A { public:

在什么情况下可以使用
reinterpret\u cast
从实际上是派生实例指针的基指针进行强制转换?(通过多态性)

如果继承是多态的,则静态强制转换不起作用

我考虑了这个琐碎的场景:

class A
{
public:
    virtual void Hello()
    {
        cout<<" A ";
    }
    virtual int GetType() { return 1; }
};

class B: public A
{
public:
    void Hello()
    {
        cout<< " B ";
    }
    void Do()
    {
        cout << " Another method of B";
    }
    int GetType() { return 2;}
};

/// ... sample/test code
A* a1 = new A();
A* b1 = new B();
A* a2;
B* b2;

if (a1->GetType() == 1)
{
    a2 = a1;
    a2->Hello();
}
else
if (a1->GetType() == 2)
{
    b2 = reinterpret_cast<B*>(a1);
    b2->Do();
    b2->Hello();
}
A类
{
公众:
虚拟void Hello()
{
coutDo();
b2->Hello();
}

请记住我曾经决定是否可以转换它们的非常幼稚的“伪类型标识方法”
GetType()
。为了避免动态类型转换,使用reinterpret类型转换是完全错误的吗?(也就是说,这是一种偏执的设计,固有的危险性和不太灵活,可能会带来不必要的麻烦吗?执行正常的动态强制转换是否更安全,是否值得付出较小的性能代价?我知道多重继承和/或虚拟继承会打乱任何其他强制转换操作,但多态/动态转换操作除外).

在这种情况下,为什么要避免使用
dynamic\u cast
呢?如果在执行cast之前必须调用一个虚拟成员函数,那么您可能要比使用
dynamic\u cast
来回答您的第一句话付出更多的代价(在性能方面)


将基指针静态转换为更派生的指针的唯一有效方法是使用
静态\u cast
,这仅在基指针为非虚拟指针时有效:

Base * b = &derived;                       // implicit Derived * => Base *

Derived * p = static_cast<Derived *>(b);   // OK, I know what *b really is
Base*b=&derived;//隐式派生的*=>Base*
派生的*p=static_cast(b);//好的,我知道*b实际上是什么
静态转换应该被认为是隐式转换的对立面

重新解释强制转换是完全错误的。(通常可以接受的唯一重新解释强制转换是用于I/O的字符指针。)


(当您有一个指向虚拟基的指针时,您别无选择,只能使用
动态\u cast
,但这当然是因为在这种情况下,基子对象仅在运行时确定。)

如果可能,您应该避免使用reinterpret\u cast,使用reinterpret\u cast的主要原因是当您处理用C编写的遗留代码时,否则应首选静态和动态转换,如果您的设计要求您使用reinterpret\u cast,您可能希望将此视为您的设计可能不是最优的提示


静态\u cast可以用于多态类型,只要您确信它们总是成功的,否则您应该使用动态\u cast。

您不能使用
重新解释\u cast
来安全地向下转换。但是您可以使用

  • static\u cast
    ,当您知道对象的动态类型是(可能派生自)您向下转换到的对象时,以及

  • 如果静态已知的类是多态的,则引用或指针的
    动态\u cast


在另一个方向上,对于向上转换,您可以(但不应该)使用C样式转换来转换到不可访问的基础。这在标准中得到了特别支持。不过,我从未找到使用它的机会。

在非B的对象上调用B方法函数是危险的。问题的标题是“安全”“另一种情况是,您的代码不安全

大多数情况下,使用动态_cast是不好的,是设计拙劣的标志

在某些情况下,它是有用的,尤其是在使用版本化插件时。您加载一个插件并获得一个可能支持或不支持新功能的对象,并且您可以动态地将您知道它支持的接口(基类)强制转换为更高版本(从该版本派生)。如果有效,您可以使用新功能,如果不可用,您必须禁用此功能或使用旧的操作方式

有时,您可以使用双重分派来执行此类操作。

我所知道的动态强制转换的唯一“安全”替代方法是使用.Example():

A类;
乙级;;
类类型访问者{
公众:
虚空访问(A&)=0;
虚空VisitB(B&)=0;
virtual~TypeVisitor()=默认值;
};
甲级
{
公众:
虚拟void Hello()
{

你是什么意思--“如果继承是多态的,静态强制转换不起作用。”<代码> STATICORCAST 是您想要的。出于某种原因,VC2010将不允许用静态Type强制转换ReExtType。这可能是一个微软特定的安全机制。@ TeoDron:我不能用MSVC 2012(Visual C++ 11)复制编译器错误。。而且我从未见过那个bug。那么你能发布一个展示那个bug的例子吗?@teodron:
静态强制转换
如果你有虚拟继承或跨分支强制转换,则不起作用。在那种情况下,只有
动态强制转换
可用。就是这样。@KerrekSB:通过一系列
静态强制转换
,是的,但在s中仅限单个快照
dynamic\u cast
may。因此,总体而言,为RTTI执行dynamic\u cast比调用虚拟方法更糟糕?编译器通常通过最多几个指针重定向来实现
virtual
成员函数(我认为,如果继承是
虚拟的
,则更为重要——如果没有
虚拟的
继承,则为2)另一方面,我知道没有一种切实可行的方法来进行
dyanmic\u cast
转换,它最终不会回到字符串比较的等效方法。现在,成功的
dyanmic\u cast
转换有时会更快…”“将基指针转换为派生指针的唯一有效方法是使用静态转换”是错误的。我看到了对转换的强调,但如果这是为了指出这个词的特殊含义,那么它就不是建立在标准或通用术语中的。好的观点,但假设一个人确信
动态_cast
的结果应该是派生类的指针,但基是虚拟的,这是唯一的选择吗?(即,使用动态强制转换与调用虚拟方法和静态CA一样昂贵吗
 A
 B
 Another method of B
 B
 Another method of B