This is really a question of good form/best practices. I use structs in C++ to form objects that are designed to basically hold data, rather than making a class with a ton of accessor methods that do nothing but get/set the values. For example:
struct Person { std::string name; DateObject dob; (...) };
If you imagine 20 more variables there, writing this as a class with private members and 40-something accessors is a pain to manage and seems wasteful to me.
Sometimes though, I might need to also add some sort of minimal functionality to the data. In the example, say I also sometimes need the age, based on dob:
struct Person { std::string name; DateObject dob; (...) int age() {return calculated age from dob;} }
Of course for any complex functionality I would make a class, but for just a simple functionality like this, is this "bad design"? If I do use a class, is it bad form to keep the data variables as public class members, or do I just need to accept it and make classes with a bunch of accessor methods? I understand the differences between classes and structs, I'm just asking about best practices.
Because the only difference between a structure and a class is that structure members have public access by default and class members have private access by default, you can use the keywords class or struct to define equivalent classes.
Member functions inside the structure: Structures in C cannot have member functions inside a structure but Structures in C++ can have member functions along with data members.
use struct for plain-old-data structures without any class-like features; use class when you make use of features such as private or protected members, non-default constructors and operators, etc.
Unlike class, struct is created on stack. So, it is faster to instantiate (and destroy) a struct than a class.
I think there are two important design principles to consider here:
Hide a class's representation through an interface if there is some invariant on that class.
A class has an invariant when there is such thing as an invalid state for that class. The class should maintain its invariant at all times.
Consider a Point
type that represents a 2D geometric point. This should just be a struct
with public x
and y
data members. There is no such thing as an invalid point. Every combination of x
and y
values is perfectly fine.
In the case of a Person
, whether it has invariants depends entirely on the problem at hand. Do you consider such things as an empty name as a valid name? Can the Person
have any date of birth? For your case, I think the answer is yes and your class should keep the members public.
See: Classes Should Enforce Invariants
Non-friend non-member functions improve encapsulation.
There's no reason your age
function should be implemented as a member function. The result of age
can be calculated using the public interface of Person
, so it has no reason to be a member function. Place it in the same namespace as Person
so that it is found by argument-dependent lookup. Functions found by ADL are part of the interface of that class; they just don't have access to private data.
If you did make it a member function and one day introduced some private state to Person
, you would have an unnecessary dependency. Suddenly age
has more access to data than it needs.
See: How Non-Member Functions Improve Encapsulation
So here's how I would implement it:
struct Person { std::string name; DateObject dob; }; int age(const Person& person) { return calculated age from person.dob; }
In C++, Structs are classes, with the only difference (that I can think of, at least) being that in Structs members are public by default, but in classes they are private. This means it is perfectly acceptable to use Structs as you are - this article explains it well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With