Union in c++ are they feasible

前端 未结 5 1800
死守一世寂寞
死守一世寂寞 2021-02-07 01:45

Can a union in C++ have a member function? How do union with data members and member functions exist if an object is created?

If I suppose yes, then are they feasible an

相关标签:
5条回答
  • 2021-02-07 02:03

    I just added some more things to @maraguida example. 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

    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.

    0 讨论(0)
  • 2021-02-07 02:04

    I don't know if it's valid. Codepad accepts, runs, and gives the expected output from this program

    union x {
      int t;
      int k() { return 42;};
    };
    
    int main() {
      x y;
      y.t = y.k();
      std::cout << y.t << std::endl;
    }
    
    0 讨论(0)
  • 2021-02-07 02:10

    9.5/1

    A union can have member functions (including constructors and destructors), but not virtual (10.3) functions. 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

    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.

    0 讨论(0)
  • 2021-02-07 02:17

    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)];
    }
    
    0 讨论(0)
  • 2021-02-07 02:23

    The union is a C-structure, and does not work well with C++ types (there are a number of caveats actually). 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!

    Behold Boost.Variant!

    You can define a boost::variant<std::string, Foo, char> and it'll make sure:

    • 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!

    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.

    0 讨论(0)
提交回复
热议问题