投掷到工会

Casting to union

本文关键字:      更新时间:2023-10-16

由于在C++中使用union的经验有限,我正在努力理解转换为该数据类型的基本机制。

假设两种类型

Type_aType_b 分别是类型 intlong 的包装器。

联合定义为:

union Type_u {
    Type_a a;
    Type_b b;
}

现在我有 Type_a 型的东西,让我们称之为 j(只是为了混淆)。 我需要将其传递给一个需要 Type_u 类型参数的函数:

void burninate(Type_u peasants);

将此变量j传递给burninate的正确方法是什么? (我在将j投射到Type_u以及按原样传递时遇到了问题。 两者都没有编译。

值得指出的是,我无法修改联合类型(或Type_a或Type_b或刻录的签名)。

由于 Type_a 是第一个元素,因此您可以像这样初始化联合:

Type_a j;
Type_u u = {j};
burninate(u);

如果要传递一种类型的Type_b

Type_b k;
Type_u u;
u.b = k;
burninate(u);

在 C 和 C++ 中对此是有区别的。在 C99 中,可以使用指定的初始值设定项来初始化不是第一个元素的元素。

Type_b k;
Type_u u = {.b = k};
burninate(u);
你可以

像这样传递j ((Type_u)j)它会起作用。

[编辑] 当这些家伙表现出难以置信时,这是代码示例尝试编译此代码,它将像魅力一样工作。

#include <stdio.h>
typedef union type_u {
    int a;
    long b;
}type;
int main ()
{
type T;
int j = 10;
    T = ((type)j);
    printf ("T.a:%d T.b:%lu n", T.a, T.b);
return 0;
}

查看 o/pXXX-mac:~ jork$ gcc union_test.cXXX-mac:~ jork$ ./a.outT.a:10 T.b:10

C++通常不会特意鼓励使用工会,如果工会成员有非平凡的构造函数和析构函数,这可能会特别尴尬,因为在这种情况下,工会自己的构造函数(分别是析构函数)将被删除,如果需要,您必须自己提供一个(您通常会这样做)。

总的来说,将非 POD 类型放入联合中可能不是一个好主意,因为语义很笨拙;通常,您不能为尚未构造的对象赋值,并且,虽然您可以使用放置 new 来构造联合的成员,但您将无法实际知道该成员以前没有被构造过。此外,如果一个成员有一个显式和非平凡的析构函数,你可以为联合提供一个显式析构函数,它可以显式调用成员的析构函数,但它怎么知道它是否必须这样做呢?

但是,如果您的工会成员是 POD,那很好,但您仍然无法将工会转换为成员或将成员类型转换为工会。(GCC 允许将其作为 C 扩展,但 afaik g++ 不会以相同的方式扩展C++。

尽管如此,没有什么能阻止您为union提供一个构造函数。例如:

union long_or_double {
  long a;
  double d;
  long_or_double(long l) : a(l) {}
  long_or_double(int i) : a(i) {}
  // etc.
  long_or_double(double d) : d(d) {}
};
int f(long_or_double u);
int main(int argc, char** argv) {
  // Both of these work, because there is an explicit constructor
  f(argc);
  f(3.7);
  // ...
}

如果您无法将构造函数添加到联合类型的定义中,我认为您能做的最好的事情就是定义一个make_union函数,为每个成员类型适当地覆盖它。

联合的工作方式与结构完全相同(唯一的区别是对象在内存中的分配方式)。所以你有Type_u你;Type_a j;U.a = j;烧伤(U);

相关文章:
  • 没有找到相关文章