I have a class with a lot of built-in type members with read/write access. Should I make them public members and provide get/set methods for each one? How about structures?
The whole reason to have accessors (getters) and modifiers (setters) is to provide yourself with an extra level of indirection.
This extra level of indirection allows you to provide a read only view of your variable to a public interface, while not allowing your data member to be changed. You could still use a private or protected setter.
Setters allow you to do special error checking, validation and corrections when a value is set. For example setDirectory(const std::string &strPath), you could make sure there is a terminating slash if the user didn't specify one. This ensures that your class state will always be valid.
Getters can also shield your members from having them exposed to allow pointers to them. By not allowing pointers to them from the outside, you can ensure that if your object goes out of scope it won't lead to a crash.
The extra level of indirection for getters/setters also allow you to be able to change the data member that they encapsulate.
With a getter you can also obtain different views of your data, example: getMinutes, when your data member is actually stored in seconds.
This is not the reason to use them, but a nice side effect of using getters and setters is that you can set a breakpoint inside your modifier for example to see exactly when it is changed.
Whether you should use them or not is a judgement call based on your need. If you have so many members that it is a huge pain to provide getters and settings you could consider storing the data members in a struct and using that struct inside your class instead. You could even provide getters/setters for an object for the whole struct at once.
If there are invariants you need to preserve, then yes. Otherwise, don't bother.
Firstly, if your class has a lot of data mamebers it is probably not well designed. You may need to consider splitting it into multiple classes or storing the data in structures such as maps.
As regards providing accessors, the question is will you ever want to modify the access, possibly preventing it. If the answer is yes, then you need access functions. On the other hand, if your class is really just a bag of bits, with no behaviour, then make it a structure.
You should use public data members only
in structures, that you don't expose to client code (eg. bind-style functors) - it's useless to protect structures that noone outside will ever get
if their types encapsulate the logic of set/getting them (eg. if you create a class ObservableAttribute)
if they are const-members in an immutable structure (you can't do much except to read them if they're immutable)
If you create a public data member, you have to be sure that its value is fully orthogonal with other members of the class. Eg., you disable future possibilities of
observing changes to the member
making the member play any part in the class' invariant
disabling access to the member
changing the implementation of the member (eg. computed vs. cached vs. stored) if performance needs it
Using get/set methods for private/protected data members is a bad design.
It causes client code to be dependent on the implementation details of your class.
Changes in your class causes changes in client code.
However get/set methods for public members can be used. But it is always good to avoid them.
Related
I have learned that I can never access a private variable, only with a get-function in the class. But then why can I access it in the copy constructor?
Example:
Field::Field(const Field& f)
{
pFirst = new T[f.capacity()];
pLast = pFirst + (f.pLast - f.pFirst);
pEnd = pFirst + (f.pEnd - f.pFirst);
std::copy(f.pFirst, f.pLast, pFirst);
}
My declaration:
private:
T *pFirst,*pLast,*pEnd;
The access modifiers work on class level, and not on object level.
That is, two objects of the same class can access each others private data.
Why:
Primarily due to efficiency. It would be a non-negligible runtime overhead to check if this == other each time you access other.x which you would have to if the access modifiers worked on object level.
It's also kind of semantically logical if you think of it in terms of scoping: "How big part of the code do I need to keep in mind when modifying a private variable?" – You need to keep the code of the whole class in mind, and this is orthogonal to which objects exist in runtime.
And it's incredibly convenient when writing copy constructors and assignment operators.
IMHO, existing answers do a poor job explaining the "Why" of this - focusing too much on reiterating what behaviour's valid. "access modifiers work on class level, and not on object level." - yes, but why?
The overarching concept here is that it's the programmer(s) designing, writing and maintaining a class who is(are) expected to understand the OO encapsulation desired and empowered to coordinate its implementation. So, if you're writing class X, you're encoding not just how an individual X x object can be used by code with access to it, but also how:
derived classes are able to interact with it (through optionally-pure virtual functions and/or protected access), and
distinct X objects cooperate to provide intended behaviours while honouring the post-conditions and invariants from your design.
It's not just the copy constructor either - a great many operations can involve two or more instances of your class: if you're comparing, adding/multiplying/dividing, copy-constructing, cloning, assigning etc. then it's often the case that you either simply must have access to private and/or protected data in the other object, or want it to allow a simpler, faster or generally better function implementation.
Specifically, these operations may want to take advantage of priviledged access to do things like:
(copy constructors) use a private member of the "rhs" (right hand side) object in an initialiser list, so that a member variable is itself copy-constructed instead of default-constructed (if even legal) then assigned too (again, if legal)
share resources - file handles, shared memory segments, shared_ptrs to reference data etc.
take ownership of things, e.g. auto_ptr<> "moves" ownership to the object under construction
copy private "cache", calibration, or state members needed to construct the new object in an optimally usable state without having to regenerate them from scratch
copy/access diagnostic/trace information kept in the object being copied that's not otherwise accessible through public APIs but might be used by some later exception object or logging (e.g. something about the time/circumstances when the "original" non-copy-constructed instance was constructed)
perform a more efficient copy of some data: e.g. objects may have e.g. an unordered_map member but publicly only expose begin() and end() iterators - with direct access to size() you could reserve capacity for faster copying; worse still if they only expose at() and insert() and otherwise throw....
copy references back to parent/coordination/management objects that might be unknown or write-only for the client code
You can access private members of a class from within the class, even those of another instance.
To understand the answer, I would like to remind you few concepts.
No matter how many objects you create, there is only one copy of one function in memory for that class. It means functions are created only once. However variables are separate for each instance of the class.
this pointer is passed to every function when called.
Now it's because of the this pointer, function is able to locate variables of that particular instance. no matter if it is private of public. it can be accessed inside that function. Now if we pass a pointer to another object of the same class. using this second pointer we will be able to access private members.
Hope this answers your question.
Copy constructor is class' member function and as such has access to class' data members, even those declared as 'private'.
why the man who made that compiler allow this behavior,
that we can see hidden members of an object (that its type is the same of the class where you access the hidden members) in copy constructor or in any method in the class.
The answer: because you when you are in the class that's mean you are the builder or the designer of the class also mean that you know all data members and methods in that class that's why he allow this behavior because you build this class you know every thing about it unlike the users of the class they haven't to know every thing about the class like you.
the idea of hiding data members or method that help the users of this class and not confused them with non important things.
That's it.
If we use constructors do we need to use setters and getters. I am totally confused between these terms could someone please elaborate.
If we use constructors do we need to use setters and getters
First of all you cannot have a class without a constructor, when you do not provide any compiler will generate them for you. You should not use setters and getters unrelated if you define your own constructor or not. When you design a class you design it's interface and then add member variables to implement that behavior and those members are internal representation of the class and outside world should not be aware of them - that is what data encapsulation is for and that's why we make them private or protected. When you add members first and then blindly provide getters and/or setters - that is a wrong approach to OOD.
Use constructors to create objects. Use getters to get information from an already existing object. Use setters to change an already existing object.
Any particular class may will need one or more of these things but not every class will need all of them. In particular immutable classes can't be modifed after they've been created so don't need setters.
The two things are very different.
A constructor is a function that is called by the system whenever an object is created. If you don't define one yourself, the compiler will provide a default one. Whatever happens, a constructor will be called exactly once for each object you create. Its purpose is usually to set up valid values for all members of the class.
By contrast, getters and setters are just regular functions — methods whose purpose is to provide access to individual members of a class (read and write acces, respectively). There is no requirement to provide one, and they are not automatically generated; conversely, if one is provided, it may be called as often as you like.
Hopefully it's clear how a constructor differs from set/getters.
I know that data in a class should be private then use getter and setter to read/modify them. But isn't it very troublesome compare to using student.scores.push_back(100) directly which saves a member function.
class Student {
public:
void addToScores(int inScore) {
scores.push_back(inScore);
}
private:
vector<int> scores;
}
In short I'm curious what people actually do in practice, always strictly private data with getter and setter?
The purpose of member functions is to expose an interface. There is no need to make getters and setters, or other trivial functions, to simply move the interfaces already implemented by members to an aggregate container object.
If the client of Student should be allowed to manipulate scores however they want, you should make scores a public member and access it the easy way. If it should be a stack with only push, pop, and top, then use the std::stack interface adaptor. If only push_back should be allowed, then you might implement addToScores. But if the only client is you, and you're not worried about other parts of the std::vector interface being abused, there's really no point in implementing a new interface.
Every interface within a program should be thoughtfully designed. Adding slapdash interfaces as a habit because standard interfaces (including the C++ default assignment operator) are "dangerous" isn't necessarily a good habit.
In practice people use classes to define new data types with new semantics that are independent of their data-members. Neither accessors nor public data members are used, but instead member functions are provided that perform the tasks relevant to the new data-type, while maintaining invariants on the data-members.
Of course, sometimes people write classes that are just aggregates of data, with no additional semantics. In this case, a struct filled with public members is appropriate.
One of the basic reasons for using Get/Set methods is controlling input type besides data encapsulation.
If you do not want to take some specific input types, let say you may not want a score outside the bounds of [0,100] interval, then you can check this condition in the Set method so that library user can not make an illogical operation.
If it's a simple read/write, you do not really have to make the data private. But if there are validations/conditions that you need to do on the data being read/written, it would make sense for it to be private.
I have learned that I can never access a private variable, only with a get-function in the class. But then why can I access it in the copy constructor?
Example:
Field::Field(const Field& f)
{
pFirst = new T[f.capacity()];
pLast = pFirst + (f.pLast - f.pFirst);
pEnd = pFirst + (f.pEnd - f.pFirst);
std::copy(f.pFirst, f.pLast, pFirst);
}
My declaration:
private:
T *pFirst,*pLast,*pEnd;
The access modifiers work on class level, and not on object level.
That is, two objects of the same class can access each others private data.
Why:
Primarily due to efficiency. It would be a non-negligible runtime overhead to check if this == other each time you access other.x which you would have to if the access modifiers worked on object level.
It's also kind of semantically logical if you think of it in terms of scoping: "How big part of the code do I need to keep in mind when modifying a private variable?" – You need to keep the code of the whole class in mind, and this is orthogonal to which objects exist in runtime.
And it's incredibly convenient when writing copy constructors and assignment operators.
IMHO, existing answers do a poor job explaining the "Why" of this - focusing too much on reiterating what behaviour's valid. "access modifiers work on class level, and not on object level." - yes, but why?
The overarching concept here is that it's the programmer(s) designing, writing and maintaining a class who is(are) expected to understand the OO encapsulation desired and empowered to coordinate its implementation. So, if you're writing class X, you're encoding not just how an individual X x object can be used by code with access to it, but also how:
derived classes are able to interact with it (through optionally-pure virtual functions and/or protected access), and
distinct X objects cooperate to provide intended behaviours while honouring the post-conditions and invariants from your design.
It's not just the copy constructor either - a great many operations can involve two or more instances of your class: if you're comparing, adding/multiplying/dividing, copy-constructing, cloning, assigning etc. then it's often the case that you either simply must have access to private and/or protected data in the other object, or want it to allow a simpler, faster or generally better function implementation.
Specifically, these operations may want to take advantage of priviledged access to do things like:
(copy constructors) use a private member of the "rhs" (right hand side) object in an initialiser list, so that a member variable is itself copy-constructed instead of default-constructed (if even legal) then assigned too (again, if legal)
share resources - file handles, shared memory segments, shared_ptrs to reference data etc.
take ownership of things, e.g. auto_ptr<> "moves" ownership to the object under construction
copy private "cache", calibration, or state members needed to construct the new object in an optimally usable state without having to regenerate them from scratch
copy/access diagnostic/trace information kept in the object being copied that's not otherwise accessible through public APIs but might be used by some later exception object or logging (e.g. something about the time/circumstances when the "original" non-copy-constructed instance was constructed)
perform a more efficient copy of some data: e.g. objects may have e.g. an unordered_map member but publicly only expose begin() and end() iterators - with direct access to size() you could reserve capacity for faster copying; worse still if they only expose at() and insert() and otherwise throw....
copy references back to parent/coordination/management objects that might be unknown or write-only for the client code
You can access private members of a class from within the class, even those of another instance.
To understand the answer, I would like to remind you few concepts.
No matter how many objects you create, there is only one copy of one function in memory for that class. It means functions are created only once. However variables are separate for each instance of the class.
this pointer is passed to every function when called.
Now it's because of the this pointer, function is able to locate variables of that particular instance. no matter if it is private of public. it can be accessed inside that function. Now if we pass a pointer to another object of the same class. using this second pointer we will be able to access private members.
Hope this answers your question.
Copy constructor is class' member function and as such has access to class' data members, even those declared as 'private'.
why the man who made that compiler allow this behavior,
that we can see hidden members of an object (that its type is the same of the class where you access the hidden members) in copy constructor or in any method in the class.
The answer: because you when you are in the class that's mean you are the builder or the designer of the class also mean that you know all data members and methods in that class that's why he allow this behavior because you build this class you know every thing about it unlike the users of the class they haven't to know every thing about the class like you.
the idea of hiding data members or method that help the users of this class and not confused them with non important things.
That's it.
This applies to several cases in my application:
I have 3 or 4 functions that belong together, one is a starting function that creates and frees the required memory structures and calls the other functions as appropriate. The other functions also call themselves repeatedly. Only the starting functions is called from outside, and only once or not at all per application-run.
Currently, I pass pointers to the memory structures from the starting function as function arguments, but the argument list is getting quite long in some cases.
Is there any argument against creating classes for all these cases and making the pointers to the memory structures members?
Definitely go for a class here. That's what objects and classes are designed for.
It seems to be a quite typical use case for classes: Just add the "memory structure" as protected member of the class and initiliaze it in the constructor.
The member functions (aka "method") than can work on the data.
If you have different, but similiar use cases, you may also make use of subclassing, so you create a base class with default implementation and create some derived class that overwrites some of the methods with an own implementation.
But note, that you could also use other members varibales to set the behaviour at runtime (e.g. a bool that is used to toggle on or off a specific behaviour).
Your question is too abstract to see what is the best solution for your case. Remember, often there are a lot of solutions - and so there is more than one good solution.
It sounds to me like these functions belong in a class - with the internal functions private or protected - likewise with the members.
Yes, relate them all within a class.
This will also give you a cleaner code which might help you minimize the functions' arguments lists.
In simple words an object can be anything you decide. Say a person. This is an object which I'll decide to define as a class if I'll write a program that needs to keep information regarding people.
There are much better explanations than this, just google/wikipedia it.