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 struct
s 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 union
s 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);