简体   繁体   English

C ++中的Union是可行的

[英]Union in c++ are they feasible

Can a union in C++ have a member function? C ++中的联合可以有成员函数吗? How do union with data members and member functions exist if an object is created? 如果创建对象,如何存在与数据成员和成员函数的联合?

If I suppose yes, then are they feasible any where. 如果我认为是,那么它们在任何地方都是可行的。 If yes then where? 如果是,那么在哪里?

9.5/1 9.5 / 1

A union can have member functions (including constructors and destructors), but not virtual (10.3) functions. 联合可以具有成员函数(包括构造函数和析构函数),但不具有虚函数(10.3)。 A union shall not have base classes. 工会不得有基类。 A union shall not be used as a base class. 联合不得用作基类。 An object of a class with a non-trivial constructor (12.1), a non-trivial copy constructor (12.8), a non-trivial destructor (12.4), or a non-trivial copy assignment operator (13.5.3, 12.8) cannot be a member of a union, nor can an array of such objects 具有非平凡构造函数(12.1),非平凡复制构造函数(12.8),非平凡析构函数(12.4)或非平凡复制赋值运算符(13.5.3,12.8)的类的对象不能是一个联盟的成员,也不是一系列这样的对象

What do you mean by How do union with data members and member functions exist if an object is created? 你是什​​么意思?如果创建了一个对象如何存在与数据成员和成员函数的联合? Member functions (non-virtual) take no space in an instance of any class/union. 成员函数(非虚拟)在任何类/联合的实例中不占用空间。

You can also make a template union : 您还可以创建模板联合:

template <typename T>
union Foo {
public:
  Foo() {}
  Foo(const T& value) : _val(value) {}

  const char* data() const {
    return _tab;
  }

  std::size_t size() const {
    return sizeof(T);
  }

  char operator[](unsigned int index) const {
      return _tab[index];
  }

private:
  T _val;
  char _tab[sizeof(T)];
}

The union is a C-structure, and does not work well with C++ types (there are a number of caveats actually). union是一个C结构,并不适用于C ++类型(实际上有很多警告)。 However there already exist a C++ equivalent, which effectively work with all C++ classes and user-defined classes and is even safer than the union! 但是,已经存在一个C ++等价物,它可以有效地处理所有C ++类和用户定义的类,甚至比联合更安全!

Behold Boost.Variant ! 看哪, Boost.Variant

You can define a boost::variant<std::string, Foo, char> and it'll make sure: 你可以定义一个boost::variant<std::string, Foo, char> ,它会确保:

  • that the appropriate constructor/destructor/assignment operator is run, when required 在需要时运行适当的构造函数/析构函数/赋值运算符
  • that you only access the lastest value that was set 您只能访问已设置的最新值

And it even comes with the excellent: boost::static_visitor<Result> which let's you apply a method on the union regardless of its type and provide compile-time checking to warn you whenever you have forgotten one of the possible types! 它甚至还带有优秀的: boost::static_visitor<Result> ,它允许你在union上应用一个方法而不管它的类型,并提供编译时检查,以便在你忘记其中一种可能的类型时发出警告!

class MyVisitor: boost::static_visitor<int>
{
public:
  int operator()(std::string const& s) const {
    return boost::lexical_cast<int>(s);
  }

  int operator()(Foo const& f) const { return f.getAsInt(); }

  int operator()(char c) const { return c; }
};

typedef boost::variant<std::string, Foo, char> MyVariant;

int main(int argc, char* argv[]) {
  MyVariant v; // the std::string is constructed

  if (argc % 2) { v = Foo(4); }
  if (argc % 3) { v = argv[1][0]; }
  if (argc % 5) { v = argv[1]; }

  std::cout << boost::apply_visitor(MyVisitor(), v) << '\n';
  return 0;
}

Also... it's as efficient (fast) as a union , and does not involve any dynamic look-up like Boost.Any would. 此外......它与union一样高效(快速),并且不涉及任何像Boost.Any那样的动态查找。

I don't know if it's valid. 我不知道它是否有效。 Codepad accepts, runs, and gives the expected output from this program Codepad接受,运行并提供此程序的预期输出

union x {
  int t;
  int k() { return 42;};
};

int main() {
  x y;
  y.t = y.k();
  std::cout << y.t << std::endl;
}

I just added some more things to @maraguida example. 我刚刚给@maraguida例子添加了一些东西。 I wrote it as a response just to heve more room. 我写这篇文章只是为了获得更多空间。 It illustrates that not only member functions, but also static member functions and operators can be added. 它说明了不仅可以添加成员函数,还可以添加静态成员函数和运算符。

#include    <iostream>

union x
 {
    int     t;
    float   f;

    int k( )        { return t * 42;};
    static int static_k( )  { return 42;};

    float k_f( )    { return f * 42.0f;};

    unsigned char operator []( unsigned int );
};

unsigned char x::operator []( unsigned int i )
{
    if ( i >= sizeof( x ) )
        return  0;

    return  ( ( unsigned char * )&t )[ i ];
}

int main( )
{
    x   y;
    y.t = x::static_k( );

    std::cout << "y.t\t= " << y.t << std::endl;
    std::cout << "y.f\t= " << y.f << std::endl;
    std::cout << "y.k( )\t= " << y.k( ) << std::endl;
    std::cout << "x::static_k( )\t= " << x::static_k( ) << std::endl;
    std::cout << "y.k_f( )\t= " << y.k_f( ) << std::endl;

    std::cout << "y[ 0 ]\t= " << ( unsigned int )y[ 0 ] << std::endl;
    std::cout << "y[ 1 ]\t= " << ( unsigned int )y[ 1 ] << std::endl;
    std::cout << "y[ 2 ]\t= " << ( unsigned int )y[ 2 ] << std::endl;
    std::cout << "y[ 3 ]\t= " << ( unsigned int )y[ 3 ] << std::endl;
}

It can be compiled with: g++ -Wall union_func.cpp -o union_func 它可以使用以下代码编译:g ++ -Wall union_func.cpp -o union_func

The output is: 输出是:

$ ./union_func 
y.t     = 42
y.f     = 5.88545e-44
y.k( )  = 1764
x::static_k( )  = 42
y.k_f( )        = 2.47189e-42
y[ 0 ]  = 42
y[ 1 ]  = 0
y[ 2 ]  = 0
y[ 3 ]  = 0

You can, for example, put a conversion operator to another type of your need, if it make sense to your need. 例如,如果符合您的需要,您可以将转换运算符置于您需要的其他类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM