ADTs & Classes An introduction
Quick review of OOP Object: combination of: data structures (describe object attributes) functions (describe object behaviors) Class: C++ mechanism used to represent an object Class definition includes: member functions member variables
Information Hiding Principle says we should only know what we need to know (to prevent getting bogged down in irrelevant detail) A class that uses information hiding in its design is an Abstract Data Type (ADT member variables hidden access to hidden members available only through member functions
Class declaration promotes information hiding class Name { public: //member functions //declared here private: //member variables //declared here }; Name is a valid identifier public section includes class parts accessible to outside world private section includes hidden parts Note semicolon!
Example object: the Nesper sign Member variables: message time & temperature Member functions: display message display time & temp change message change time & temp
class Nesper { public: void display_message ( ) const; void display_tnt ( ) const; void change_message (char[] text); void change_tnt (int temp, clock current); private: char message[25]; int temperature; clock time; };
Class definition: public section class Nesper { public: void display_message ( ) const; void display_tnt ( ) const;... Public section contains member function prototypes Keyword const indicates that the functions declared here do not change the object
Class definition: public section... void change_message (char[] text); void change_tnt (int temp, clock current); Change functions are examples of modifiers - - member functions that alter the calling object change_tnt includes a parameter (current) that is an example of an ADT variable
Class definition: private section private: char message[25]; int temperature; clock time; }; Member variables declared here Can be variables of built-in types, arrays or pointer, or instances of objects defined elsewhere
Where do they go? Class declaration: header file (xxxx.h) Member function definitions: definition file xxxx.cpp (same name as header -- different extension) should not include a main( ) function Class instances: user program
Implementing member functions #include <iostream.h> #include <cstring.h> #include <assert.h> void Nesper::change_message (char[] text) { assert (strlen(text)<25); message = text; } Preprocessor directives for all needed library routines Class name and scope operator (::) indicate this is a member function
Notes on member functions Every instance of a class (object) has its own copies of all class members, including member functions A member function is called by the object that owns it (can have several objects of same class in a program) Member functions may call other member functions
Using a class in a program #include nesper.h int main( ) { Nesper sign1, sign2;... Preprocessor directive indicates class definition should be included Declaring Nesper variable instantiates the class sign1 and sign2 are objects of type Nesper
Using a class in a program Member function is sign1.change_message activated by calling ( This is my sign ); object sign1.display_message( ); Syntax:... calling_object. function_name (argument(s));
Constructors Special member function Automatically called when an object is instantiated Unique characteristics: Constructor name is same as class name Constructor has no return value (not even void) Can have multiple constructors for a class -- example of function overloading classes2 15
Why define constructors? Can define a class without one; in this case, compiler uses automatic default constructor memory allocated for member variables constructors for individual members are called, if they exist With defined constructor, can do more -- including initializing member variables classes2 16
Constructor Prototypes class Nesper { public: Nesper (string msg); // initializes message Nesper (int temp); // initializes temperature Nesper (clock tm); // initializes time Nesper ( ); // default constructor classes2 17
Notes on Function Overloading Can have as many functions with the same name in a class as you wish Compiler differentiates between the functions by their parameter lists A constructor that requires no arguments is the default constructor -- will be called under most circumstances classes2 18
Calling a constructor Constructor is called when an object is declared: Nesper stopsign ( Stop! Stop, I say! ); // calls first ctor in class Nesper midnight (12:00); // calls ctor with clock parameter Nesper sign; // calls default constructor classes2 19
Constructor implementation Nesper::Nesper (string msg) { message = msg; } classes2 20
Another example: default ctor Nesper::Nesper( ) { message = Your message here ; temperature = 32; time = 12:00; } classes2 21
Default arguments Functions can be declared with default values listed for their parameters Provides flexibility for constructors: can be called with or without arguments can be called with some, but not all arguments specified if no arguments are specified, default values are used classes2 22
Nesper constructor with default arguments class Nesper { public: Nesper (string msg = Your message here, int temp = 32, clock tm = 12:00);... Default arguments are specified in the function prototype, not the implementation When function is called, can omit some or all arguments -- may be omitted starting from right classes2 23
Examples of function calls Nesper mysign ( Taurus, 65, 4:30); // all defaults replaced by actual arguments Nesper yoursign ( Pisces ); // msg replaced by argument; use defaults for // remaining values Nesper sign; // most common -- defaults used for all values classes2 24
Implementation of function with default arguments Nesper::Nesper (string msg, int temp, clock tm) { } message = msg; temperature = temp; time = tm; Implementation is identical to version that called for the same parameters but didn t use default arguments Default arguments appear only in prototype classes2 25
One more variation: inline functions Inline functions are defined (implemented) within the class definition Saves a little execution time (no function call, no return) Can be inefficient in terms of memory (can end up with many copies of same compiled code Best for extremely simple, one-liner functions classes2 26
Inline constructor example class Nesper { public: Nesper( ) { message = Your message ; temperature = 32; time = 12:00; }... Inline functions aren t usually used for constructors, unless the object is very small This is still just one function declaration within class definition classes2 27
Value semantics Operations that determine how values are copied from one object to another object of the same class type Assignment operator Copy constructor: constructor that instantiates an object which is an exact copy of its argument classes2 28
Automatic assignment example Nesper sign1( Hi, 32, 1:00), sign2; // sign2 has default values sign2 = sign1; // sign2 now has same // values as sign1 Can use automatic assignment when the object doesn t use dynamic memory Later we ll see how to define the assignment operation for classes that require it classes2 29
Automatic copy constructor Nesper sign1; Nesper sign2(sign1);... Nesper sign3 = sign1; First object uses default constructor Both second and third objects use copy constructor, even though third example looks like assignment Like automatic assignment, must be explicitly defined for some classes classes2 30
Assignment vs. copy constructor Assignment copies information from one existing object into another existing object Copy constructor declares and initializes a new object, which is a copy of an existing object classes2 31
#ifndef NESPER_H #define NESPER_H One more look at Nesper.h // macro guard -- use to ensure that class declaration // only appears once in a program -- safeguard // to prevent linking errors in large programs class Nesper { public: Nesper (string msg= Your message, int temp=32, clock tm=12:00); void display_message( ) const; void display_tnt( ) const; void change_message (string); void change_tnt (int temp, clock tm); private: string message; int temperature; clock time; }; #endif classes2 32
Overloading operators Have already seen function overloading in action -- multiple constructors Can also overload operators -- including logical, arithmetic & I/O If you want to be able to use these operations on a new class, you must overload them for the class operator overloading 33
Example class Fraction { }; public: Fraction (int num=1, int den=1); int get_num( ) const; int get_den( ) const; private: int numerator; int denominator; Consider the following declaration: Fraction f1, f2; What is the result of the following code? if (f1 = = f2) cout << They are equal ; Yes, it s a trick question! operator overloading 34
Overloading logical operators -- example bool operator = = (const Fraction& f1, const Fraction& f2) // precondition: f1 & f2 are Fractions reduced to LCD form // postcondition: returns true if f1 = = f2, false otherwise { return (f1.getnum( ) = = f2.getnum( ) && f1.getden( ) = = f2.getden( )); } operator overloading 35
Can use one overloaded operator to define another bool operator!= (const Fraction& f1, const Fraction& f2) { return!(f1 = = f2); } operator overloading 36
Notes on operator overloading Still leaves ordinary uses of operator available -- compiler uses context to determine which instance of = = or!= to use Binary operators are generally not declared as class member functions it s syntactically legal, but: no longer binary -- becomes operation performed on only one of the operands operator overloading 37
Overloading arithmetic operators As with binary comparison operators, binary arithmetic operators usually implemented as non-member functions Can overload more than one instance of an operator on same data type -- this is how, for example, it s possible to multiply a double by a double, but also a double by an int operator overloading 38
Overloading multiplication on Fractions Fraction operator * (const Fraction& f1, const Fraction& f2) { int n, d; n = f1.getnum( ) * f2.getnum( ); d = f1.getden( ) * f2.getden( ); Fraction result (n,d); return result; } operator overloading 39
General notes on binary operator overloading Syntax pattern: return type operator symbol (operand type& op1, Define as non-member functions operand type& op2); If access to private members is required, must provide for this can be done with get functions, as we ve seen can also be done by other means, shown shortly operator overloading 40
Overloading insertion & extraction Already overloaded for the basic types Can also be overloaded for new classes Once overloaded, will work on all stream types operator overloading 41
Example: overloading insertion ostream& operator << (ostream& o, const Fraction& f); Return type & first argument are output stream references -- this allows chaining Insertion must be defined as a non-member function Function use: Fraction half; cout << half; operator overloading 42
Function implementation ostream& operator << (ostream& o, const Fraction& f) { o << f.getnum( ) << / << f.getden( ); return o; } operator overloading 43
Overloading extraction istream& operator >> (istream& i, Fraction& f); Prototype similar to insertion -- same points apply Problem: accessor functions haven t been defined in Fraction class to put new values in an existing Fraction, and non-member functions can t access private members operator overloading 44
Possible solutions Define member functions to set values of numerator & denominator, then call these in operator >> function would be functional but defeats information hiding Better solution: make operator >> a friend function operator overloading 45
Friend function Non-member function that has access to private members of a class To declare a friend function, place its prototype in the class definition preceded by the keyword friend: friend istream& operator >> (istream& i, Fraction& f); operator overloading 46
Function implementation istream& operator >> (istream& i, Fraction& f) { char slash; // reads divider character i >> f.numerator >> slash >> f.denominator; return i; } operator overloading 47