两个dynamic_cast问题

时间:2011-06-15 07:31:07

标签: c++ dynamic-cast

  1. 您是否会在频繁运行的方法中使用动态强制转换?它有吗? 开销很大?

  2. dynamic_cast返回的指针究竟是什么?指向同一地址的指针? 指向不同实例的指针?我缺乏这种理解。更具体 - 我希望只有在运行时才能对父类型的指针进行赋值 原来是一个儿子类型的指针。溶液

  3. 谢谢。

5 个答案:

答案 0 :(得分:6)

dynamic_cast可帮助您在执行向下转换时检查有效性。

如果无法安全地下载指针或引用,则返回NULL或引发异常(std::bad_cast为引用)。

您是否会在频繁运行的方法中使用动态强制转换?是否有很大的开销? dynamic_cast确实使用了一些额外的RTTI(Run Time Type Information)来确定演员表的有效性。所以肯定有一个开销。通常,typeinfo的{​​{1}}指针将添加到type。我通常说,因为虚拟机制本身是编译器实现依赖的细节(可能因不同的编译器而异)。

您必须使用一些好的分析工具来分析您的代码,以确定调用virtual table是否会反复降低代码的性能。

dynamic_cast返回的指针究竟是什么?指向同一地址的指针?指向不同实例的指针?

我们更容易理解,而不是使用dynamic_cast分析向下转换,我们会分析向上转播。如果类型为dynamic_cast,而另一种类型base继承自derived,则base类型将包含类型为derived的子对象。当指向base对象的指针被上传到指向derived的指针时,操作的结果将是base子对象里面的地址 {{ 1}}。执行base恢复该操作,并返回一个指向derived对象的指针,该对象在作为参数传递的地址中包含dynamic_cast子对象(derived也是如此,但它将应用可能的偏移量而不实际检查运行时类型。)

在最简单的情况下,使用单个(非虚拟)继承,base子对象将对齐static_cast,但在多重继承的情况下,情况并非如此:

derived

该程序将打印basestruct base { int x; virtual void foo() {} }; struct another_base { virtual void bar() {} }; struct derived : base, another_base {}; int main() { derived d; base * b = &d; // points to the base subobject inside derived another_base * o = &d; // points to the another_base subobject inside derived std::cout << std::boolalpha << ( static_cast<void*>(b) == dynamic_cast<derived*>(b) ) << "\n" << ( static_cast<void*>(o) == dynamic_cast<derived*>(o) ) << std::endl; } 。请注意,如果要比较它们,则必须显式地将其中一个指针转换为true,否则编译器将执行 downcasted 指针的隐式向上转换。

答案 1 :(得分:1)

如果方法“频繁运行”并不重要,只有在运行它对所需性能产生重要的负面影响时才会这样。找到它的唯一方法是分析你的代码。

返回的指针只是一个指针。您需要发布示例代码以澄清问题的后半部分。如果你的意思是:

Base * p1 = ....;

Derived * d = dynamic_cast<Derived*>(p1);
if ( d ) {
     (*d) = "foobar";
}

如果Derived支持赋值,那就很好了。

答案 2 :(得分:1)

  

您是否会在频繁运行的方法中使用动态强制转换?它有很大的开销吗?

它没有太大的开销。但这取决于编译器的RTTI实现。但是,不要过早优化。

  

dynamic_cast返回的指针究竟是什么?指向同一地址的指针?指向不同实例的指针?我缺乏这种理解。更具体 - 只有在运行时它被证明是一个指向子类型的指针时,我希望对父类型的指针进行赋值。溶液

派生类的任何对象都包含其基类的对象。 dynamic_cast返回指向其中一个对象的指针(当类只继承一个基类时,它通常是相同的指针,但如果类继承多于1个基类,则它不是相同的指针)。但这取决于使用过的编译器。

答案 3 :(得分:0)

  1. 查看此帖How to profile my C++ application on linux的已接受答案。它涵盖了调用valgrind的选项以及用于查看配置文件结果的应用程序。

  2. 动态强制转换将返回您使用与参数相同的地址转换的类型的指针,因此它指向同一个对象。当动态将“son”类型转换为“父类型”时,如果参数不是“son”类型,则动态转换将抛出std :: bad_cast异常。

答案 4 :(得分:0)

  

dynamic_cast返回的指针究竟是什么?指向同一地址的指针?指向不同实例的指针?我缺乏这种理解。更具体 - 我希望对父类型的指针进行赋值,只有在运行时它才会成为指向子类型的指针。

假设你有

class Base { ... };
class ChildA : public Base { ... };
class ChildB : public Base { ... };

ChildA childa;
ChildB childb;

Base * ptra = &childa;
Base * ptrb = &childb;

ChildA * ptra_as_ChildA = dynamic_cast<ChildA*>(ptra); // == &childa
ChildA * ptrb_as_ChildA = dynamic_cast<ChildA*>(ptrb); // == NULL
如果指向对象是目标类的实例或从目标类派生的类,则

dynamic_cast将返回非空指针。如果指向的对象不是目标类的实例,则返回空指针。

注意:输入到dynamic_cast的指针指向的确切内存位置和dynamic_cast返回的指针可能不一样。示例:假设ChildA继承自两个类,Base和SomeInterface。您可以static_cast一个指向Base指针和SomeInterface指针的ChildA指针。这两个父类指针中的至少一个不会指向与ChildA指针相同的内存位置。动态转换这两个父类指针中的任何一个都会返回原始的ChildA指针。