How to Choose Between Struct or Class
“Should I use a struct
, or a class
?”
Such is the question we sometimes ask ourselves when creating a new type.
What’s the difference between struct
and class
in C++? How to to choose one or the other?
This is the question we tackle in this week’s video:
Transcript of the video:
What’s the difference between a struct
and a class
? And more importantly, when should we use one or the other? That’s what we’re talking about today on Fluent C++.
Let’s start by the difference between a struct
and a class
. The legal difference: there is no difference at all.
Well, that’s a lie but a very small and insignificant one. The only technical difference is that if you don’t say anything about scoping, what’s in the struct
is going to be public
whereas what’s in a class
is going to be private
.
It also goes for inheritance: if a struct
inherits from something else and you don’t specify if is is a public
or private
inheritance:
struct Derived : Base { };
the inheritance is public
. And for a class
it would be private
.
Of course, you can have public
and private
members and inheritance if you just write it, in either struct
or class
.
Apart from that there is absolutely no difference. You can do anything in struct
that you would do in class
: a struct
can have inheritance, public
, private
, protected
members, virtual
methods, templates, overloads, SFINAE, what have you.
So how do we make a choice whether to use a struct
or a class
? It comes down to convention. Choosing between struct
or class
out of convention allows to express your intent when you create a new type.
The convention for a struct
is: a struct
is a bundle. A struct
is just there to stitch things together. Several objects, like several objects that come out of a function for example. You can then use struct
to express that there is no unity and that it’s just a bundle.
Actually, there’s a question you may ask: what’s the difference between a struct
and a pair
(or a tuple
) in that regard? Indeed, the pair
(or tuple
) also puts things togethers in a bundle.
The difference between a struct
and a pair
(or tuple
) is that the struct
has a name. So if there’s a name that makes sense over the bundle of things you’re putting together, you’d rather use a struct
. If there’s absolutely no name and those things only happen to be together at the same place and time, then you’d use a pair
or tuple
.
In this regard, the struct
rises the level of abstraction of the bundle a little, by giving it a name. And that names characterizes what that bundle represents.
Now about class
. A class
does things, that’s the essence of a class
. It has responsibilities, which are represented by the methods of its interface. You don’t care about what data there is in the class
when you’re a user of that class
. Actually it may not even have any data at all and that doesn’t matter. What matters is its interface.
So a class rises the level of abstraction much more than a struct
does, because it hides an implementation behind an interface that describes what this class can do.
Another thing that a class
can do is implementing invariants. An invariant is a property that must hold true all the time in a class
from the perspective of the client of that class. For example, say in a string, you have a buffer than contains the characters populating the string, and also a size in the string. And from the perspective of the user of that string, you want that the size corresponds to the actual number of characters in the string.
The contract of a class
is the constructor puts those invariant in place, and all the methods assume that those invariants are verified.
A struct
doesn’t do that at all: a struct
is a bundle where you can see right through it, and there is no relation between its members.
Today, that’s pretty much all we have to describe a type: struct
or class
. But in a distant future we may have more than that, with the metaclasses proposal. But that’s a topic for another video.
We’re going to end this video by reading the titles of 4 of the C++ Core Guidelines from which I took inspiration to structure this video.
Organize related data into structures (struct
s or class
es)
Use class
if the class has an invariant; use struct
if the data members can vary independently
Represent the distinction between an interface and an implementation using a class
Use class
rather than struct
if any member is non-public
If you like this video feel free to share it, subscribe to the Fluent C++ channel, and put a thumb up!
Thanks, and I see you next time.
Related posts:
- The right question for the right name
- The metaclasses proposal in less than 5 minutes (next week)
Share this post!