将 void 指针转换为动态类型

Convert void pointer to a dynamic type

我正在尝试将 void 指针转换为动态类型。 例如,我将 double 变量传递给 test1 函数,我希望 sum 函数可以工作。但是我在 sum(*reinterpret_cast<myType*>(tmp)) 上收到 C2664 无法转换参数错误。 如果我使用它,它将起作用。

double c= *reinterpret_cast<double*>(tmp); 
sum(c);

我该如何解决这个问题?

void sum(double a)
{
    cout << "sum:" << a+10 << endl;
}
  
void test1(void* tmp)
{
    typedef decltype(tmp) myType;
    sum(*reinterpret_cast<myType*>(tmp));
}

int main()
{
    double a = 87.7;
    test1(&a);

    return 0;
}

首先,动态类型只有在使用继承时才真正有意义。例如,如果您有这样的代码:

class Base {};

class Derived : public Base {};

int main() {
    Base *b = new Derived;
}

在这种情况下,b 的静态类型为 Base *,但动态类型为 Derived *(因为它被声明为指向 Base 的指针, 但实际上指向 Derived).

的一个实例

因此,如果您想恢复实际的动态类型,您需要从定义一些基 class 和一些派生 class(es) 开始,并在它们之间进行转换。 When/if 你这样做,你通常想使用 dynamic_cast 而不是 reinterpret_cast 来完成这项工作(它会自动检查实际类型,所以如果你尝试转换,转换将失败到它不是真正指向的类型)。但在大多数情况下,您希望在基 class 中定义某种虚函数,并根据需要在派生 class 中覆盖它,因此您不需要使用 dynamic_cast 根本。另请注意,dynamic_cast 仅适用于包含至少一个虚函数的 classes(但如果您使用 public 继承而没有任何虚函数,则您可能做错了什么) .

或者,您基本上可以创建一个受歧视的联盟。您需要存储一些东西来记录存储的实际类型,并且您将使用它在需要时转换回正确的类型。

enum type { FLOAT, DOUBLE };

struct value { 
    type t;
    void *value;
};

float f = 1.2f
double d = 3.2;

value v { FLOAT, &f };
value y { DOUBLE, &d };

void do_call(value v) {
    if (v.type == FLOAT) { 
        use_float(*reinterpret_cast<float *>(v.value));
    else if (v.type == DOUBLE)
        use_double(*reinterpret_cast<double *>(v.value));
}

但是,编译器不会在 void * 中存储任何内容来跟踪它真正指向的对象类型。如果你想从 void * 转换回 floatdouble ,你将不得不存储一些东西来跟踪实际是哪种类型。

而不是后者,您可能还想研究使用 std::variant,它会自动处理存储类型标签,并且还可以帮助自动化大多数类型调度(例如,使用 std::visit).至少在通常使用的情况下,这将更像是一个实际的标记联合,因此它存储实际值,而不是指向存储在其他地方的值的指针。