Classes - Part II (revisited) n Constant objects and member functions n Definition Form of Member Functions n friend functions and friend classes n Constructors (Default, Copy, Conversion, Value) n Picturing (data members in) Objects n static Free Functions in a Class Definition
Constant Member functions/objects n Constant objects l const Elevator southElevator(1234,0); l any attempt to modify the state of this object will result in error l eg: southElevator.moveToFloor(4); l a compile time error l const objects can help optimize the performance l non-constant member functions cannot be invoked from const objects : eg: southElevator.moveToNextFloor() n Constant member functions l void Elevator::showStatus() const; l no member of the function belonging to Elevator class can change state. l Const member functions cannot call non-const member functions l a const member function can be overloaded with a non-const version (decision to use which one is based on the object const or not)
Definition Form: Member Functions The names of members defined in a.cpp file are fully qualified names: prefaced by the name of class in which they are members, with the scope operator :: separating the class name from the member name l This includes the names of constructors and member functions Also remember that if default arguments appear in a member function declaration (in the.h file), they cannot appear in the matching member function definition in the.cpp file n Member functions can access an object’s private members n When one member function directly calls another, it is in the same context (using the same object, i.e, same data members) that the first member function was called on
The Array Class class Array { public: Array (int = 10); // default constructor Array (const Array& R); // copy constructor ~Array() ; // destructor //... other member declarations void initArray(); int Size () const; private: int size; // size of the array int *ptr; // pointer to the first element of the array };
Constructor/Destructor Definitions Array::Array(int arraySize) { size = (arraySize > 0 ? arraySize : 10) ptr = new int [ size] ; assert ( ptr != 0) ; // make sure memory is allocated for (int i = 0; i <size ; i++) ptr[ i ] = 0; } // copy constructor Array::Array(const Array &A) : size( A.size) { ptr = new int [ size] ; assert ( ptr != 0) ; // make sure memory is allocated for (int i = 0; i <size ; i++) ptr[ i ] = A.ptr[ i ]; } //destructor Array :: ~ Array() { delete [] ptr; }
Access to private Members The statements in the definition of a member function in a class can directly access all the members declared in that class, including its private members In fact, most data members are declared to be private A class may also declare private member functions Such functions can be called directly by functions defined in that class (by the programmer who wrote the class); like private data members, they cannot be called directly from an object (by the user of a class) For example, the programmer cannot arbitrarily change size of the array. I.e. Object.size = 78 would be illegal (a compile error) The users of the class are not permitted to change the private data members of a class. Only a behavior(if provided) can change the private states.
Mutators and Accessors Note that initArray() is declared as a mutator (no const ) l It changes the data members in a controlled way, ensuring that the values entered by the user conform to the requirements of the class invariants The behavior Size is declared as an accessor ( const ) These functions examine (and return) but do not change the value of private data members Often a class supplies accessors for each private data member (so users of a class can examine each of these values by calling a member function) n In both cases the member functions are quite small. l This if the norm for member functions: each performs a small, well defined action on the data members of an object; their definitions do not get too big l It is the composition of these coordinated (but small) service that make classes easily reusable
Constructors n Constructors are used to instantiate (initialize) class objects. l Constructors have the same name as the class l Constructors have no return types l Constructors act as middle men: the user gives them values for initializing private data members (which the user cannot do); it can store these values in the private data members l For data members that are primitive, not other classes, we could write assignment statements instead: for example Array::Array(): size(0.){}
Data Members in Classes and Objects n Each object constructed from a class stores its own values for its data members l The constructor for the class indicates how to initialize all its data members, whenever an object of the class is constructed l Constructors normally use initializers to declare/construct and initialize the data members of that object Usually all data members are declared private, they cannot be examined or stored-into directly by the user of that class: Accessors provide the values of private data members without compromising data security l A class mutator can change the value of a private state. l There will be no direct access to private members of a class to users of the class. l The only access is provided through mutators or accessors.
Friend Functions and Classes n Private members of a class restrict access to all objects that are not members of the class. n A friend function is defined outside the scope of a class but has the right to access all class members. l Eg: class Account{ friend void SetPassWord(Account &); } n Friend functions are also very useful in the context of operator overloading n Classes can be declared to friends of other classes. l If class A is a friend of class B, then members of A can access all members of B, but not vice versa. (just the way real life is) l Two way friendships must be declared, not implicit
Constructor Categories - Revisited There are four constructors categories n Default: usable with no arguments Use: Array A; //size of A is initialized to default n Copy: usable with one argument (of that same class) l Use: Passing an argument by copy/value to a function n Conversion: usable with one argument of another type/class Use: Implicit conversion: e.g., 1 + Array(1,2) (here, 1 can be converted to an array containing ones before addition) n Value: arbitrary parameters, often one per data member Use: Array A(35,1); // size and initial values n The following is both a default and conversion constructor Array (int size = 10, int initValue = -1);
The special constant this this is a special constant declared implicitly in every class; we can use it inside any member function l Technically it is a pointer to the object that the member function was called on It is used mostly in the form *this When a function must return a reference to the object (as in operator= ) you will see the statement: return *this; Note that the meaning of accessing a member by writing just its name inside a member function (say, the member M ) is the same as writing ( *this).M or this->M. It specifies accessing the member M of this object -the object that the current member function has been called on Pragmatically, *this is not used to access members (which are accessed directly by their name), but is instead mostly as it is in the operator= member function, when the whole object must be returned
static Free Functions n Sometimes a class’s implementation needs to define and use a function that is not a member function n Such a function is called a free function (as opposed to a member function) The Array class can define and use the free function static int arrayCount() All such functions should be declared static, which makes them declared only in the.cpp file in which they appear: such functions are not declared (meaning that they cannot be called) outside the.cpp file n This is another example of name protection l It restrict the access to a function only to other functions defined in its file scope
Member Functions Defined... … in class declarations Instead of defining a member function in a matching.cpp file, we can define it in a.h file For example, we could declare and define the Numerator member function in the rational.h file by int Numerator () const {return my_Numerator;} This kind of definition is normally considered bad form, because it clutters the.h file with implementation information that users of that class do not need to see (they want to focus on what a function does, not how) l We will learn, in a later lecture, that it is perfectly acceptable to use this combined form of declaration/definition when we declare/define very small (degenerate) classes
Class Pragmatics n Designing classes for re-use is hard l The skill we are focusing on is (re)using classes that others have already defined (and tested, debugged, etc.) n Every class should l Declare a default constructor s This will be most useful when we learn about arrays/vectors of classes l Declare a copy constructor This is useful when passing objects to parameters, although most objects will be passed as either reference or const reference Declare operator= s This operator is quite useful: it is similar to the copy constructor, but instead of constructing an object and initializing its data members, it copies the values of its parameter object into an existing object It also ends with return *this; Overload operator<< to write out an object’s value