2

The classes and structs have one difference between them (as far as I know), that the struct defaults to public and class defaults to private. And then I came to know that there is a similar kind of data type which is also used in a similar manner, that is union. The union can not be used as a base class in inheritance (i don't know what that means, but I still accept it).

I wanted to know whether there are some particular instances, where struct/ union/ class, or they can be used interchangeably (except for the cases I enlisted)? Please do tell me if I am wrong somewhere. Regards

Sumit Gera
  • 1,249
  • 4
  • 18
  • 34

5 Answers5

7

My use of class, struct and union is the following:

  • class for objects that have behaviour.
  • struct for passive data.
  • union for very special cases where different data requires to be accessed as different types.

I've read this (except the union point) in the Google C++ Style guide a long time ago and I was following it since then.

Using structs to carry passive data (objects without behaviour attached to the object) have the advantage of default publicness of the members, so they can be accessed without Getters and Setters. If some member data needs to be checked/modified before assign or some member data needs to be computed/modified before be getted, IMHO they need a Setter/Getter pair and the object is a class instead of a struct.

For the union type, I find it useful for some kind of data structures that requires some weird access to the members, or needs some members to be treated as another type in some contexts. For example a 3D vector or a IP address:

union 3DVector
{
    double x, y, z;
    double vector[3];
} v;

// Acess members with name
v.x = 6.0; v.y = 7.0; v.z = 8.0;
// Acess members as a vector
Normalize(v.vector);

union IPAddress
{
    int binary;
    char octet[4];
} ip;

// Acess the binary address
std::cout << std::hex << ip.binary << '\n';
// Print in a human-readable form
std::cout << static_cast<int>(ip.octet[0]) << '.'
          << static_cast<int>(ip.octet[1]) << '.'
          << static_cast<int>(ip.octet[2]) << '.' 
          << static_cast<int>(ip.octet[3]) << '\n';

The above functionality could be achieved overloading operators and conversion operators, but the union approach looks neat for me.

The unions can also be templated and can have constructor/destructor, this could be useful for serialization purposes (not for all kind of objects):

template <typename T> union Serializer
{
    Serializer(const T &o) : object(o) {}
    T object;
    char binary[sizeof(T)];
};

SomePODObject obj; // Only POD objects please!
Serializer s(obj);
SendBuffer(s.binary);
PaperBirdMaster
  • 12,806
  • 9
  • 48
  • 94
  • 1
    Using `union` for binary serialization is almost always a bad idea for platform-variability and other reasons. To serialize integers portably, use bitwise tricks (easy). To serialize floats, use `ldexp` and family plus knowledge of the exact float representation you're serializing to/from (painful). To serialize objects, use the serializations for the members. –  Oct 03 '13 at 01:02
3

A union and a class or structure are completely different. A union is several things at the same time, say it can be both a character array and an integer, while a class or structure is one and only one thing that encapsulates some logically connected information, as well as optionally some logic for manipulating it. The use cases for unions and the other two are quite different.

I usually use a structure when I only store some data, while if I also need some logic associated with it(i.e. I need to add methods) I use a class.

Ivaylo Strandjev
  • 69,226
  • 18
  • 123
  • 176
  • when do you use a union? And how would you support your statement with this "A union is a user-defined data or class type that, at any given time, contains only one object from its list of members (although that object can be an array or a class type)."? I got this from http://msdn.microsoft.com/en-us/library/5dxy4b7b(v=vs.80).aspx – Sumit Gera Jan 23 '13 at 14:03
  • @IvayloStrandjev that's undefined behavior. The Q is tagged C++, not C. – Luchian Grigore Jan 23 '13 at 14:07
  • 1
    @LuchianGrigore in fact I use this `hack` to find endianess on a machine. I am not sure what you mean by the second part of your comment. There is no such thing as class in `C` and also I try to give my view of when one uses class and when struct in my answer. – Ivaylo Strandjev Jan 23 '13 at 14:10
  • I wasn't talking about class/struct (that part is correct), but your use of union. I mentioned C because AFAIK reading another union member than the one last assigned to is allowed in C, but not in C++. Your "hack" is just UB. – Luchian Grigore Jan 23 '13 at 14:11
  • @LuchianGrigore seems it works in [c++ too](http://ideone.com/GPGUvo) I am not sure what `UB` means – Ivaylo Strandjev Jan 23 '13 at 14:15
  • UB is undefined behavior. It means it can appear to work, but anything can happen. It might as well not work. It might crash or format your hard drive. – Luchian Grigore Jan 23 '13 at 14:17
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/23228/discussion-between-ivaylo-strandjev-and-luchian-grigore) – Ivaylo Strandjev Jan 23 '13 at 14:20
2

I never use union. If you end up looking at this, you better try boost variant. The only acceptable situation where we can use this is when we really need to have a deep control over the content, like custom serialization. But I would run out of this in many cases.

Also, structure are used for storing only data. If you need to add any function/method, convert it into a class.

Gaetan
  • 488
  • 4
  • 13
0

There are some areas where I may use a struct over a class:

  • If I want to define an interface type that contains only pure virtual methods. This aligns with the notion that struct defaults to public.
  • Pure data-only types, where there is no behavior attached to the type.
  • Policy or trait types, as a matter a personal preference.

The union is neither a class or a struct. I only used them in C to create discriminated or variant types at a time when memory was a premium. In C++, I don't see much of an advantage in typical applications, but may still be used in embedded or low-memory applications.

0

Typically structs and unions are used together in C when one is accessing registers. A struct can define each bit and allow for each bit in the register to be set individually. A union will allow all the bits to be changed or accessed at the same time.

Even in C++ one needs a way to setup the hardware and write to the registers of the chip.