I've just been browsing and spotted the following...
When should you use a class vs a struct in C++?
The consensus there is that, by convention, you should only use struct for POD, no methods, etc.
I've always felt that some types were naturally structs rather than classes, yet could still have a few helper functions as members. The struct should still be POD by most of the usual rules - in particular it must be safe to copy using memcpy. It must have all member data public. But it still makes sense to me to have helper functions as members. I wouldn't even necessarily object to a private method, though I don't recall ever doing this myself. And although it breaks the normal POD rules, I wouldn't object to a struct having constructors, provided they were just initialise-a-few-fields constructors (overriding assignment or destructors would definitely be against the rules).
To me a struct is intuitively a collection of fields - a data structure node or whatever - whereas a class is an abstraction. The logical place to put the helper functions for your collection-of-fields may well be within the struct.
I even think I once read some advice along these lines, though I don't remember where.
Is this against accepted best practice?
EDIT - POD (Plain Old Data) is misrepresented by this question. In particular, a struct can be non-POD purely because a member is non-POD - e.g. an aggregate with a member of type std::string. That aggregate must not be copied with memcpy. In case of confusion, see here.
For what it's worth, all the standard STL functors are defined as structs, and their sole purpose is to have member functions; STL functors aren't supposed to have state.
EDIT: Personally, I use
struct
whenever a class has all public members. It matters little, so long as one is consistent.I tend to use
struct
a lot.For the "traditional" OOP classes (the ones that represent a specific "thing"), I tend to use
class
simply because it's a common convention.But most of my classes aren't really OOP objects. They tend to be functors, and traits classes and all sorts of other more abstract code concepts, things I use to express myself, rather than modelling specific "things". And those I usually make
struct
. It saves me having to type the initialpublic:
, and so it makes the class definition shorter and easier to get an overview of.I also lean towards making larger, more complex classes
class
. Except this rarely affects anything, because I lean even more towards refactoring large, complex classes... And then I'm left with small simple ones, which might be madestruct
's.But in either case, I'd never consider it "evil". "Evil" is when you do something that actively obfuscates your code, or when you make something far more complex than necessary.
But every C++ programmer knows that
struct
andclass
mean virtually the same thing. You're not going to be confused for long because you see astruct Animal {...};
You know that it's a class designed to model an animal. So no, it's not "evil" no matter which way you do it.You said, "To me a struct is intuitively a collection of fields - a data structure node or whatever". What you are describing is Plain Old Data. The C++ standard does have an opinion of what POD means with respect to C++ language features. I suggest that, where possible, you adopt the meaning of POD used in C++0x.
I need to find a reference for this, but I thought that, as far as type definitions are concerned, the keywords "struct" and "class" are to be synonyms in C++0x. The only difference being that class defaults to private members, while a struct defaults to public. This means that you'll never see complier error messages like "Type X first seen using struct, now seen using class." once we're all using C++0x.
I think that it is wrong to have strict rules on when to use class and when to use struct. If consistency is important to you, the go ahead and make a coding standard that has what ever sort of rules you like. Just make sure everyone knows that your coding standard relates to how you want you code to look - it doesn't relate to the underlying language features at all.
Maybe to give an example where I break all your rules, you say "To me a struct is intuitively a collection of fields - a data structure node or whatever - whereas a class is an abstraction." When I want to write a class that implements some abstraction, I define the interface as a struct with pure virtual methods (egad!) - this is exposed in a header, as too is a factory method to construct my concrete class. The concrete class is not exposed i a public header at all. Since the concrete class is a secret, it can be implemented however I like and it makes no difference to external code.
I'd suggest that if you think that the keywords struct and class have any relation to the concept of POD, then you're not understanding C++ yet.
When I have control over the style guides, everything is defined as a
struct
. Historically, I wanted all my objects to be one or the other, since I was taught it was undefined behavior to forward declared a struct as a class, and vice versa (I'm not sure if this was ever actually true, its just what I was told). And really,struct
has the more reasonable default state.I still do the same because I've never been convinced of the value of using it as a form of documentation. If you need to convey that an object only has public members, or doesn't have any member functions, or whatever arbitrary line you chose to draw between the two, you have actual documentation available for that. Since you never actually use the
struct
orclass
keyword when using the type, you would need to go hunting for the definition anyhow if you want the information. And with everybody having their own opinion on whatstruct
actually means, its usefulness as self-documentation is reduced. So I shoot for consistency: everything as one or the other. In this case,struct
.Its not a popular way of doing things, to say the least. Fortunately for everybody involved, I very rarely have control over the coding standards.
I use a
struct
whenever I need an aggregate ofpublic
data members (as opposed toclass
, which I use for types that come with a certain level of abstractions and have their dataprivate
).Whether or not such a data aggregate has member functions doesn't matter to me. In fact, I rarely ever write a
struct
without also providing at least one constructor for it.As far as the language is concerned, it doesn't matter, except for default
private
vs.public
access. The choice is subjective.I'd personally say use
struct
for PODs, but remember that "POD" doesn't mean "no member functions". It means no virtual functions, constructors, destructor, oroperator=
.Edit: I also use
struct
s for simplepublic
-access aggregates of data, even if their members aren't PODs.