In the OO concept topic Objects & Classes it was explained that objects are miniature programs complete with a set of member functions with which to send them messages and a set of internal data called data members. The syntax to access a member function is:-
Object.MemberFunction(); and ObjectPtr->MemberFunction();Exactly the same syntax can be used to access its data i.e.:-
Object.DataMember; and ObjectPtr->DataMember();but, its a very bad thing to do!!.
To explain why, let's look at our Track class again:-
class Track { // Constructors and Destructors Track(Float_t mass, Float_t energy);> Track::Track(); ~Track(); // Getters and Setters Float_t GetEnergy(); void SetEnergy( Float_t energy); // Data Float_t fEnergy; Float_t fMass; Float_t fMomentum; };The C++ syntax allows us to address an object's data directly, so we could copy the energy of track A to track B simply by:-
MyTrackB.fEnergy = MyTrackA.fEnergy;so why bother with GetEnergy and SetEnergy? Well, for two very good reasons:-
void Track::SetEnergy( Float_t energy ) { fEnergy = energy; fMomentum = sqrt( fEnergy*fEnergy - fMass*fMass ); }so not only sets the energy but also the momentum to ensure internal consistency. Letting a user fiddle with an object directly will mean they will break it - you know what users are!
It would appear that we pay a high price for protecting our track's data - each access costs a subroutine call. However C++ is smart, for simple getters and setters, it will replace the function call with in-line code. So although we have to write:-
energy = MyTrack.GetEnergy();the compiler generates:-
energy = MyTrack.fEnergy;so there is no loss in performance.
How do we specify which bits of an object a user can access and which are off-limits? - by using the access control specifiers public and private. Now our Track class looks like this:-
class Track { public: // Constructors and Destructors Track(Float_t mass, Float_t energy);> Track::Track(); ~Track(); // Getters and Setters Float_t GetEnergy(); void SetEnergy( Float_t energy); private: // Data Float_t fEnergy; Float_t fMass; Float_t fMomentum; };Now anyone can use the constructors, destructors, getters and setters, but nobody can touch the data. A class definition can have multiple public and private sections, but its normal to start with the public ones so that a user, who just wants to see the public part of an object, can stop once the private part is reached. Until the first access specifier is supplied, the default is private - so until now our Track class has been useless - we could not even create an object as the constructors were private!
There is a third type of specifier: protected. That will be discussed in the OO concept:- Inheritance
It can happen that one class acts as a helper for another and has to have full access to it. Such a helper class is designated as a friend by the class being helped. An example of this type of access can be found in ROOT's container classes. Along with each container class that holds collections of objects there is an associated iterator class that knows how to sequentially retrieve each member in turn. The relationship between a container and its iterator is very close and may require that the iterator be a friend of the container.