Rossella Lau Lecture 5, DCO10105, Semester B, DCO10105 Object-Oriented Programming and Design Lecture 5: Class construction Encapsulation Class construction in C++ Constructors and other members Private and public Default, constant, and reference parameters Simple operator overload Class and ADT Static members Header file and implementation file -- By Rossella Lau
Rossella Lau Lecture 5, DCO10105, Semester B, When a user program uses function in array.cpp, the user program must maintain its own array together with the size of the array It should also take care of when to re-size the array if there is not sufficient room (slots) for new items Every user program should take care of both data and this kind of “housekeeping” work! Any way to hide the details of these works? The problem
Rossella Lau Lecture 5, DCO10105, Semester B, Encapsulation To pack data and functions inside a place – a class, e.g., for array.cpp, we can construct a class: class IntArray { int *array; int _size; // number of slot used int _capacity; // number of slot available void fillData(); void printData();. void resize( int size ); };
Rossella Lau Lecture 5, DCO10105, Semester B, Use of a class Then every user program instantiates an object from the class and accesses the members in the class instead of maintaining, e.g., the array and the size int main() { IntArray scores; // Instantiation scores.fillData(); // Member assess. scores.printData(); } To use members of a class, use the access operator “.” – see example program testIntArray.cpp
Rossella Lau Lecture 5, DCO10105, Semester B, Class and Object A class encapsulates the data and the data’s associated behavior A class can also be treated as a template An object is an instance of a class that includes actual value(s) of the data members as well as the “ability” to manipulate its data through the function/method members An object is created by instantiating from a class Instantiate: to create with initialization
Rossella Lau Lecture 5, DCO10105, Semester B, Class and Structure Former C does not support class but structure A structure can store any combination of data so a group of data can be represented by a structure (and can be represented as a type), e.g., a quadratic equation should have three data a, b, and c struct Quadratic{double a, double b, double c}; Quadratic equation; However, a structure does not incorporate functions which manipulate the respective data
Rossella Lau Lecture 5, DCO10105, Semester B, Constructors The user program declares an object variable of IntArray should use constructors of the class Default constructors Copy constructors Other constructors (with parameters) The main functionality of constructors is to initialize data members of the class Constructors should have the same identifier as a class Some people refer a constructor a function while some insist that constructors are not functions A constructor does not have return type
Rossella Lau Lecture 5, DCO10105, Semester B, Default constructors A default constructor in a class definition has the form: ClassName (void){ … } If a program does not define one, the compiler will generate one by filling binary zero to all data members A user program uses default constructor to instantiate that an object has the form: ClassName objectName ; // Inside the class IntArray(void) { _size=0; _capacity=10; array = new int[_capacity]; } // Invoke default constructor IntArray scores;
Rossella Lau Lecture 5, DCO10105, Semester B, Initialization list Since constructors are to initialize the data members, C++ supports programmers by using an initialization list to assign simple initial values: e.g., IntArray( ) : _size(0), _capacity(10) { array = new int[_capacity]; } The initialization list follows the symbol “:” and is before the definition (implementation) of the constructor The names on the list refer to data members while values inside parenthesis refer to local variables It is more of a “C++ style” to use initialization list instead of traditional assignment of initialization
Rossella Lau Lecture 5, DCO10105, Semester B, Define a copy constructor A copy constructor in a class definition has the form: ClassName (ClassName const & rhs) { … } If a program does not define one, the compiler will generate one with bit-by-bit copying // Inside the class IntArray(IntArray const & rhs) : size(rhs.size()), capacity(rhs.capacity()) { array = new int[capacity()]; for (int i=0; i < size, i++) array[i] = rhs.array[i]; }
Rossella Lau Lecture 5, DCO10105, Semester B, Invoke a copy constructor A user program uses copy constructor to instantiate that an object has the form: ClassName object1(object2); or old style: ClassName object1 = object2; // Invoke copy constructor IntArray s1 (s2);
Rossella Lau Lecture 5, DCO10105, Semester B, Design techniques with C++ support In the above example, the parameter is a constant reference parameter Use of a reference parameter is more efficient when the parameter is not in basic data type Instead of copying the whole object which may be large in size, it only copies the “address” of the actual parameter value Use of keyword “ const ” prevents the actual parameter from being modified by this constructor – avoid side effects even when using reference parameter
Rossella Lau Lecture 5, DCO10105, Semester B, Other constructors Other than default and copy constructors, a constructor can be in other forms with different parameters: ClassName (Type1, Type2,,,,) { … } A user program uses this kind of constructor to instantiate that an object has the form: ClassName object1(arg1, arg2, …); // Inside the class IntArray(int capacity) : _size(0), _capacity {capacity) { array = new int[capacity()]; } // Invoke the constructor IntArray scores(300);
Rossella Lau Lecture 5, DCO10105, Semester B, Default parameters The above constructor is quite similar to the default constructor with the only difference being that the default constructor has a default value of 10 for the capacity C++ supports default parameter which allows a parameter to have a default value if the constructor/function invoking does not give one With this technique, the definition of the two constructors can be combined into one: IntArray(int capacity=10): _size(0), _capacity(capacity) { array = new int[capacity()]; }
Rossella Lau Lecture 5, DCO10105, Semester B, Other functions A user program after instantiation of an object from a class can access other functions in the class; e.g., scores.fillData() which is quite similar to the way we used functions in array.cpp except that now every function should be invoked by an object Indeed, there are typical functions of a class in C++ Accessors – to view the values of data members Mutators – to modify the values of data members Destructor – to clean up storage occupied by data members Services methods (or functions)
Rossella Lau Lecture 5, DCO10105, Semester B, Accessor Usually, its name starts with “get” e.g., getDatum1(), getDatum2(), etc There are also other kinds of accessors such as size() in vector<> ; therefore, for IntArray, it can add: size() to return the used slots of the array [] to return the element with a valid array index [] is not a valid function name but is required since [] does not apply for a class C++ supports operator overload to allow a class to define its own function for normal operators using in C++
Rossella Lau Lecture 5, DCO10105, Semester B, Operator Overload (introduction) returnType operatorop(parameter list) const E.g., int operator[](int i) const {return array[i];} “const” here supports that the object being invoked will not be modified To invoke this “new” operator for IntArray, simply use: e.g., cout << scores[i]; sum+= scores[i]; which is the same as using an array but scores in this case is an instance of IntArray; also, scores[i] must be on right hand side of an assignment
Rossella Lau Lecture 5, DCO10105, Semester B, Mutator Usually, its name starts with “set” e.g., setDatum1(), setDatum2(), etc There are also other kinds of mutators such as push_back() in vector<> ; therefore, for IntArray, it can add: push_back() to add an element after the last used slot if there is still room, otherwise, resize the array then add the element resize(int) to modify the value of capacity together with resizing the array; see IntArray.cpp [] to return the reference of an element which is going to be modified int & operator[] (int i) { return array[i];} With this definition, scores[i] can be on the left hand side in assignment
Rossella Lau Lecture 5, DCO10105, Semester B, Services methods Methods other than constructors, accessors, mutators, and destructors can be called as services, utilities, and similar names To invoke services, accessors, and mutators (other than operator overload functions), simply use the “access” operator “.” with an object: e.g., scores.fillData(), scores.printData() The way to invoke methods also leads to the name of “object based programming”.
Rossella Lau Lecture 5, DCO10105, Semester B, Destructor It has the form: ~ ClassName() Java does not need a destructor since all garbage collection is done by the virtual machine “java” In C++, whenever dynamic storage is allocated (by “new”), deallocation must be performed in the destructor in order to release the dynamic storage It is not required if no dynamic storage is allocated in the class For IntArray, it must have one: ~IntArray() {delete[] array;} Note that a user program cannot invoke a destructor, a destructor is automatically invoked by the system at the end of an object’s life (its scope, the execution of the respective function)
Rossella Lau Lecture 5, DCO10105, Semester B, Who is responsible Members in a class can be accessed through the “access” operator; i.e., we can also identify data members; e.g., scores._size However, it means any user programs can modify data members of a class Every user program needs to take care of the housekeeping work when modifying the data Which user program is responsible for data modification? Class should be able to hide something
Rossella Lau Lecture 5, DCO10105, Semester B, Information hiding with private Usually, data members are declared with “private” and most of the constructors and functions are declared with “public” Private members cannot be accessed outside the class – i.e., an application program cannot modify private members In C++, without specifying “private” or “public”, the default is “private”
Rossella Lau Lecture 5, DCO10105, Semester B, class IntArray { int *array; int _size; // number of slot used int _capacity; // number of slot available IntArray(size_t capacity=10); ~IntArray();. void resize( int size ); void fillData(); void printData();. }; IntArray with public and private private: public:
Rossella Lau Lecture 5, DCO10105, Semester B, Class and ADT A class is, indeed, the implementation of an Abstract Data Type (ADT) An ADT defines the logical properties of data type, the domain (range, valid values) of its data, and operations of the data without the detailed implementation In defining the operations, usually an ADT also specifies the precondition and postcondition of an operation Example: Malik: Example 12-8
Rossella Lau Lecture 5, DCO10105, Semester B, Underlying concepts A class is a collection of data and functions, called members, of the class which can be imagined as a template or an ADT of something An object is an instance of a class Members can be classified as “private” and “public” to the outsiders, they are called “member access specifiers” A function member can access any other member in the class (no matter if they are private or public)
Rossella Lau Lecture 5, DCO10105, Semester B, Coding style for class definition Usually, a class definition has the following styles: Note that many programmers also like to put private data members at the end of a class class ClassName { private: …… // data members public: …… // constructors …… // destructor …… // accessors …… // mutators …… // services };
Rossella Lau Lecture 5, DCO10105, Semester B, Interface file and implementation file In C++, usually the function definition is not placed inside the class definition Just similar to array.h and array.cpp, the class definition is similar to an ADT and is convenient to be included by other user programs as the interface file while the implementation can be defined in an separate file as the implementation file E.g,. IntArray.h and IntArray.cpp
Rossella Lau Lecture 5, DCO10105, Semester B, Notes on implementation file When implementing function definition of class members, the class name together with the scope resolution operator “::” must be used; e.g., void IntArray::fillData() { … }
Rossella Lau Lecture 5, DCO10105, Semester B, More typical examples Quadratic.h and Quadratic.cpp enum TypeValues {value1, value2, …}; this – to reference an object of itself, it is a pointer and need to use to identify its members getXXX() and printXXX() are services of accesors and output function Malik’s 12: clockType.h and clockType.cpp
Rossella Lau Lecture 5, DCO10105, Semester B, Static members of a class A class can have static members, data and functions Static data members will NOT be instantiated for each object but only be a single copy for all objects of the same class Static function members can only access non-static members of a class and they are not invoked by a class object; they are invoked by the class name; e.g., illustrate::incrementY(); Example: Malik’s 12:10-11 Static members are not really “object based” (but “class based”) and they should be avoided as much as possible
Rossella Lau Lecture 5, DCO10105, Semester B, Summary A class encapsulates the detailed data and their respective functions including constructors (default constructor, copy constructor, and others), destructor (optional), accessors, mutators, and other service methods With the accessibility of private and public, a class can support real information hiding C++ implementation styles support many design techniques: constant for side effect avoidance, reference parameter supports efficient process, default parameter supports shorter coding A class supports object based programming that is an extension of structured programming
Rossella Lau Lecture 5, DCO10105, Semester B, Reference Malik: 12, 11:1, 8:1 -- END --