In C++, the only technical difference between a struct and a class is that, by default (i.e., if you don’t specify anything), members of struct are public while members of a class are private. You can achieve encapsulation in a C++ struct by setting up a private section, and putting your data members and your internal member functions into that section. Likewise, a C++ struct can also have protected members in a protected section.
So, technically speaking, you can achieve the very same things with struct or class…only the default access is different. This near equivalence was implemented in C++ because it was easy to implement it in the language. The default public access for struct members was done for backward compatibility with C, so that a C struct would just compile and everything would be automatically public, just as it always is in C. The fact that you can have private members, protected members, and member functions in a struct, well, that’s just thrown in for free. Keep in mind that, just because something is free, doesn’t mean it’s worth using.
If you can effectively achieve the same thing with either a struct and class, and you are always explicit with public, protected, and private sections, which one should you use when?
Well, the language doesn’t enforce this, but nearly every coding standard and organization I’ve worked with uses classes for objects and structs for plain old data (POD). In other words, when you don’t need a full-fledged object, but you just need to lay out a chunk of data, use struct. Otherwise, use class. This is an expectation many professional developers have, so if they’re reading the code and see struct, they’ll immediately think “plain old data.” If they see a class, they’ll immediately think “full-fledged object.” You want to follow the principle of least astonishment. Don’t surprise the reader by using a struct for a full-fledged object or a class for plain old data. It will slow the reader down, and thus increase the cost of maintaining the code.
For example, let’s say you need to deal with a file format that has a well-defined file header area with many fields in it. All you need to do is read the header into memory and access the fields in the header. There may be no need for construction, destruction, member functions, etc. You just need access to the data, by name, at the correct offsets, overlaid on the buffer you read in. In this case, you would use a struct, because you’re dealing with plain old data. The same might be true for a well-defined communication packet header. In other words, you would use a struct in C++ the same way you would use a struct in C.
Bottom line: Use class for a full-blown object. Use struct for plain old data.
You wouldn’t expect some part of the post to appear below the bottom line, but there is one overriding factor to consider. If your project or team or local coding standard uses different criteria to choose between struct and class in C++, you should follow whatever conventions they use. It is far more important to be consistent across an entire project than to follow an industry norm. It’s great if the two are in sync, but they aren’t always in sync in the real world.