标签: dynamic-cast

C++中dynamic_cast的真实例子

任何人都可以给我一个真实世界的例子,说明当需要dynamic_cast并且根本无法解决时?我能想到的例子通常可以解决双重调度问题.

如果约束太强,那么一般来说,dynamic_cast的示例也很好.

我希望看到真实的例子,而不是"它通常用于在类型树之间向上和向下转换".

c++ dynamic-cast

12
推荐指数
1
解决办法
3755
查看次数

当您使用多重继承时,静态转换是否安全?

我发现自己处于一种我知道什么类型的东西的情况.Type是三个(或更多)继承级别之一.我调用返回的工厂B*但是T是一个类型的最高级别(如果我的代码知道它是什么)或第二级别.

无论如何,我static_cast在模板中做了一个错误的事情.我的问题是我什么时候可以安全地静态施放?有没有这样的时间?我在这种情况下做到了,因为当我意外地将T作为古怪的东西(已经发生并且)动态转换忽略(并返回null)时,我宁愿得到编译错误.但是,当我知道正确的类型时,指针未被调整,导致我有一个错误的指针.我不确定为什么在这种情况下允许静态转换.

我什么时候可以安全地使用static_cast进行向下铸造?有没有情况?现在似乎总是错误地使用a static_cast(当目的是向下投射时)

好的,我想出了如何重现它.

#include <iostream>
struct B { virtual void f1(){} };
struct D1 : B {int a;};
struct D2 : B {int a, b; };
struct DD : D1, D2 {};

int main(){
void* cptr = new DD(); //i pass it through a C interface :(
B*  a = (B*)cptr;
D2* b = static_cast<D2*>(a); //incorrect ptr
D2* c = dynamic_cast<D2*>(a); //correct ptr
std::cout << a << " " <<b << " " …
Run Code Online (Sandbox Code Playgroud)

c++ dynamic-cast static-cast

12
推荐指数
2
解决办法
7591
查看次数

`*dynamic_cast <T*>(...)`是什么意思?

最近我查看了一个开源项目的代码,我看到了一堆表单的声明T & object = *dynamic_cast<T*>(ptr);.

(实际上这是在宏中发生的,用于声明遵循类似模式的许多函数.)

对我而言,这看起来像是一种代码味道.我的理由是,如果你知道演员阵容会成功,那么为什么不使用static_cast?如果你不确定,那么你不应该使用断言进行测试吗?由于编译器可以假设任何指针*都不是null.

我问过一位关于irc的开发者,他说,他认为static_cast沮丧是不安全的.他们可以添加一个断言,但即使他们没有,他说你仍然会得到一个空指针取消引用并在obj实际使用时崩溃.(因为,在失败时,dynamic_cast会将指针转换为null,然后当您访问任何成员时,您将从某个非常接近零的值的地址读取,操作系统将不允许这样做.)如果使用a static_cast,和它变坏了,你可能会得到一些内存损坏.因此,通过使用该*dynamic_cast选项,您可以在速度上进行折衷,以获得更好的可调试性.你没有为断言付费,相反,你基本上依靠操作系统来捕获nullptr dereference,至少这是我所理解的.

我当时接受了那个解释,但它让我感到困扰,我又想了一些.

这是我的推理.

如果我理解标准权利,static_cast指针转换基本上意味着做一些固定的指针算术.也就是说,如果我有A * a,我静将它转换为一个相关的类型B *,什么编译器实际上正在与做的就是添加一些偏移指针,偏移量只取决于类型的布局A,B(和其可能的C++实现).void *在静态演员之前和之后,可以通过静态铸造指针和输出它们来测试该理论.我希望如果你看一下生成的程序集,static_cast将会变成"向指针对应的寄存器添加一些固定常量".

一个dynamic_cast指针强制手段,首先检查RTTI和只做静态浇铸如果基于动态类型是有效的.如果不是,那就回来吧nullptr.于是,我想到的是,编译器会在某个点扩大为一个函数dynamic_cast<B*>(ptr),其中ptr的类型是A*到像表达

(__validate_dynamic_cast_A_to_B(ptr) ? static_cast<B*>(ptr) : nullptr)
Run Code Online (Sandbox Code Playgroud)

但是,如果我们再*在dynamic_cast的结果,*nullptr是UB,因此我们看好隐含的nullptr分支从未发生过.并且合规编译器被允许从中"向后推"并消除空检查,这是克里斯拉特纳着名的博客文章中的一个点驱动的家.

如果测试函数__validate_dynamic_cast_A_to_B(ptr)对优化器是不透明的,即它可能有副作用,那么优化器就无法摆脱它,即使它"知道"nullptr分支没有发生.但是,这个函数可能对优化器不透明 - 可能它对其可能的副作用有很好的理解. …

c++ dynamic-cast casting undefined-behavior c++11

12
推荐指数
1
解决办法
783
查看次数

为什么C++编译器不会从最终类中优化这个dynamic_cast?

考虑这个类层次结构:

struct Animal { virtual ~Animal(); };
struct Cat : virtual Animal {};
struct Dog final : virtual Animal {};
Run Code Online (Sandbox Code Playgroud)

我的理解是,将finalclass Dog确保没有人能够创建一个类继承Dog,其中,推论,意味着没有人能够创建IS-A类Dog和IS-A Cat同时进行.

考虑这两个dynamic_cast:

Dog *to_final(Cat *c) {
    return dynamic_cast<Dog*>(c);
}

Cat *from_final(Dog *d) {
    return dynamic_cast<Cat*>(d);
}
Run Code Online (Sandbox Code Playgroud)

GCC,ICC和MSVC忽略final限定符并生成调用__dynamic_cast; 这是不幸的,但并不令人惊讶.

让我感到惊讶的是,Clang和Zapcc都为("总是返回nullptr")生成了最佳代码from_final,但是生成了对__dynamic_castfor 的调用to_final.

这真的是一个错过的优化机会(在一个编译器中显然有人投入一些努力来尊重final演员阵容中的限定符),或者在这种情况下,由于某些微妙的原因,我仍然没有看到优化是不可能的?

c++ polymorphism dynamic-cast final

12
推荐指数
1
解决办法
397
查看次数

有没有办法在C#中进行动态隐式类型转换?

给定此类具有隐式转换运算符:

public class MyDateTime
{
    public static implicit operator MyDateTime(System.Int64 encoded)
    {
        return new MyDateTime(encoded);
    }

    public MyDateTime(System.Int64 encoded)
    {
        _encoded = encoded;
    }
    System.Int64 _encoded;
}
Run Code Online (Sandbox Code Playgroud)

我现在可以做以下事情:

long a = 5;
MyDateTime b = a;
Run Code Online (Sandbox Code Playgroud)

但不是以下内容:

long f = 5;
object g = f;
MyDateTime h = g;
Run Code Online (Sandbox Code Playgroud)

这给出了编译时间:

无法将类型'object'隐式转换为'MyDateTime'.

我感觉合理.

现在我修改前面的例子如下:

long f = 5;
object g = f;
MyDateTime h = (MyDateTime)g;
Run Code Online (Sandbox Code Playgroud)

编译好了.现在我得到一个运行时InvalidCastException:

无法将"System.Int64"类型的对象强制转换为"MyDateTime"类型.

这告诉我C#隐式转换运算符仅在编译时应用,并且在.NET运行时试图将对象动态转换为另一种类型时不应用.

我的问题:

  1. 我对么?
  2. 还有其他方法可以做到这一点吗?

顺便说一句,完整的应用程序是我Delegate.DynamicInvoke()用来调用一个带MyDateTime参数的函数,而我传递给的参数的类型很DynamicInvoke长.

c# dynamic-cast type-conversion implicit-cast dynamic-invoke

11
推荐指数
1
解决办法
2949
查看次数

`dynamic_cast`从Base到Derived

是的,我知道dynamic_cast如果Base不是多态的话,使用downcast 无法编译,但我的问题与此无关.

class Base {
    public:
        virtual void bar()
        {
            cout << "bar\n";
        }
};

class Derived: public Base {
    public:
        void foo()
        {
            cout << "foo\n";
        }
};

int main()
{
    Base *pb;
    Derived *pd;

    pb = new Derived;  //Base* points to a Derived object
    pd = dynamic_cast<Derived*>(pb); 
    pd->foo();  //outputs foo

    pb = new Base;  //Base* points to a Base object
    pd = dynamic_cast<Derived*>(pb);  
    pd->foo();  //outputs foo, too. Why?
}
Run Code Online (Sandbox Code Playgroud)

我以为pb = new Derived; …

c++ dynamic-cast

11
推荐指数
3
解决办法
8071
查看次数

断言中的dynamic_cast导致错误

我正在使用过时的Visual Studio 2008(让我省去麻烦"这就是你的问题".)这似乎是Visual Studio的一个问题:http://rextester.com/XKFR77690这似乎是一个问题assert宏:http://ideone.com/bhxMi0

鉴于这些结构:

struct base { virtual ~base() {} };

template <typename T>
struct Foo : base { T foo; };
Run Code Online (Sandbox Code Playgroud)

我可以做这个:

base* test = new Foo<pair<int, int>>;

if(dynamic_cast<Foo<pair<int, int>>*>(test) != NULL) cout << "hello world\n";
Run Code Online (Sandbox Code Playgroud)

但是当我在if-statement中使用完全相同的代码时assert:assert(dynamic_cast<Foo<pair<int, int>>*>(test) != NULL)我得到一个错误:

警告C4002:宏assert
错误C2143的实际参数太多:语法错误:缺少','之前')'

顺便说一句,我可以通过使用C风格的演员来解决这个问题:assert((Foo<pair<int, int>>*)(test) != NULL)但我认为C风格演员阵容static_cast不是dynamic_cast我不想要的.

c++ gcc assert dynamic-cast visual-studio

11
推荐指数
2
解决办法
301
查看次数

dynamic_cast混乱

我放弃了......

$ 5.2.7/2-"如果T是指针类型,则v应该是指向完成类类型的指针的右值,结果是类型为T的rvalue.如果T是引用类型,则v应为左值一个完整的类类型,结果是T引用的类型的左值."

根据以上所述,以下代码应该是格式良好的.

struct A{};
struct B : A{};

int main(){
   B b;
   A a, &ar1 = b;

   B& rb1 = dynamic_cast<B&>(ar1);  // Does not $5.2.7/2 apply here?
   B& rb2 = dynamic_cast<B&>(a);    // and also here?
}
Run Code Online (Sandbox Code Playgroud)

但事实并非如此.所有编译器都抱怨dynamic_cast的操作数不符合多态

$ 5.2.7/6-否则,v应该是多态类型的指针或左值(10.3).

所以我的问题是$ 5.2.7/2是什么意思?为什么$ 5.2.7/6会在这里踢?

c++ dynamic-cast

10
推荐指数
2
解决办法
2914
查看次数

C++ dynamic_cast - 多态需求和向下转换

在下面的代码中,在构造obj案例1时,我们也构造了一个derived类对象,但它的成员函数是不可访问的obj.因此,在向下转换(即,在情况2中),使用obj作为源时,我们已经在其中构造derived了它.为什么obj需要多态?

如果我把我与上面的描述混淆了,为什么obj在向上转换时不需要多态,但是在向下转换时它确实需要在使用时具有多态性dynamic_cast

class base
{
public:
    base()
    {
        cout<< " \n base constructor \n";
    }
};

class derived : public base
{
public:
    derived()
    {
        cout << " \n derived constructor \n";
    }
};

base *obj = dynamic_cast<base*> (new derived); // case 1: explicitly upcasting
derived *OBJ = dynamic_cast<derived*> (obj);   // case 2: error
Run Code Online (Sandbox Code Playgroud)

c++ dynamic-cast downcast

10
推荐指数
2
解决办法
1万
查看次数

在共享库中显式化实例化模板化类和dynamic_cast

我今天偶然发现了一个问题,似乎无法解决.我正在编译一个共享库,其中包含一个模板化的类(Derived<T>,其基础是Base)以及该类的一些显式实例化.我希望库用户从这个模板化的类扩展.当我尝试将出现问题dynamic_cast的用户的情况下,从Base*Derived<T>*.

我已将问题缩小到这个MWE:

共享库包含以下文件:

Base.h

#ifndef BASE_H_
#define BASE_H_

class Base {
public:
    Base();
    virtual ~Base();
};

#endif /* BASE_H_ */
Run Code Online (Sandbox Code Playgroud)

Derived.h

#ifndef DERIVED_H_
#define DERIVED_H_    
#include <Base.h>

template <typename T>
class Derived : public Base {
public:  
    Derived();
    virtual ~Derived();
};

#endif /* DERIVED_H_ */
Run Code Online (Sandbox Code Playgroud)

Derived.cpp

#include <Derived.h>

template <typename T>
Derived<T>::Derived() :
    Base() {
}

template <typename T>
Derived<T>::~Derived() {
}

// explicit instantiations
template class Derived<float>;
template class …
Run Code Online (Sandbox Code Playgroud)

c++ templates dynamic-cast shared-libraries

10
推荐指数
1
解决办法
1663
查看次数