您会在频繁运行的方法中使用动态转换吗?它有很大的开销吗?
dynamic_cast 返回的指针到底是什么。指向同一地址的指针?指向不同实例的指针?我缺乏这种理解。更具体地说——我希望对父类型的指针进行赋值,前提是在运行时它是指向子类型的指针。解决方案?
谢谢你。
您会在频繁运行的方法中使用动态转换吗?它有很大的开销吗?
dynamic_cast 返回的指针到底是什么。指向同一地址的指针?指向不同实例的指针?我缺乏这种理解。更具体地说——我希望对父类型的指针进行赋值,前提是在运行时它是指向子类型的指针。解决方案?
谢谢你。
dynamic_cast
帮助您在执行向下转换时检查有效性。
std::bad_cast
如果指针或引用不能安全地向下转换,它返回 NULL 或抛出异常(对于引用)。
您会在频繁运行的方法中使用动态转换吗?它有很大的开销吗?
dynamic_cast
确实使用了一些额外RTTI(Run Time Type Information)
的东西来确定演员表的有效性。所以肯定会有开销。通常,指向 的指针typeinfo
将type
添加到virtual table
. 我通常说,因为虚拟机制本身是依赖于编译器实现的细节(可能因不同的编译器而异)。
您将不得不使用一些好的分析工具来分析您的代码,以确定dynamic_cast
重复调用是否会降低代码的性能。
究竟是什么返回的指针dynamic_cast
。指向同一地址的指针?指向不同实例的指针?
当我们分析upcasting而不是分析downcasting时,更容易理解。给定一个类型和另一个继承自的类型,该类型将包含一个 type 的子对象。当指向对象的指针向上转换为指向的指针时,操作的结果将是内部子对象的地址。执行 a会恢复该操作,并返回一个指向包含作为参数传递的地址中的子对象的对象的指针(做同样的事情,但它将应用可能的偏移量而不实际检查运行时类型)。dynamic_cast
base
derived
base
derived
base
derived
base
base
derived
dynamic_cast
derived
base
static_cast
在最简单的情况下,使用单一(非虚拟)继承,derived
子对象将对齐base
,但在多重继承的情况下,情况并非如此:
struct 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
, false
。请注意,void*
如果要比较它们,则必须显式转换其中一个指针,否则编译器将对向下转换的指针执行隐式向上转换。
该方法是否“经常运行”并不重要,只要运行它对所需性能有重要的负面影响。找出这一点的唯一方法是分析您的代码。
返回的指针只是一个指针。您需要发布示例代码来澄清问题的后半部分。如果你是这个意思:
Base * p1 = ....;
Derived * d = dynamic_cast<Derived*>(p1);
if ( d ) {
(*d) = "foobar";
}
如果 Derived 支持分配,那很好。
您会在频繁运行的方法中使用动态转换吗?它有很大的开销吗?
它没有很大的开销。但这取决于编译器对 RTTI 的实现。但是,不要过早优化。
dynamic_cast 返回的指针到底是什么。指向同一地址的指针?指向不同实例的指针?我缺乏这种理解。更具体地说——我希望对父类型的指针进行赋值,前提是在运行时它是指向子类型的指针。解决方案?
派生类的任何对象都包含其基类的对象。dynamic_cast 返回指向这些对象之一的指针(当类仅继承一个基类时,它通常是同一个指针,但如果类继承了多个基类,则它不是同一个指针)。但这取决于使用的编译器。
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。您可以将 ChildA 指针静态转换为 Base 指针和 SomeInterface 指针。这两个父类指针中的至少一个不会指向与 ChildA 指针相同的内存位置。动态转换这两个父类指针中的任何一个都将返回原始 ChildA 指针。
请参阅这篇文章How to profile my C++ application on linux的公认答案。它涵盖了调用 valgrind 的选项以及查看配置文件结果的应用程序的良好 gui。
动态转换将返回您转换的类型的指针,其地址与参数相同,因此它指向同一个对象。当将“son”类型动态转换为“father”类型时,如果参数不是“son”类型,动态转换将抛出 std::bad_cast 异常。