260 likes | 266 Views
Learn about const in C++ classes, its importance, and how to use it correctly. Explains const objects, const member functions, and parameters. Also covers dynamic memory allocation and good programming practices.
E N D
CMSC 202 More C++ Classes
Announcements • Project 1 due midnight Sunday 2/25/01 • Quiz #2 this week • Exam 1 Wednesday/Thursday • Project 2 out Monday March 5th
const • Use “const” (constant) whenever possible • Supports the concept of “least privilege” • Objects may be const • Member functions may be const • Parameters may be const
const Objects • We’ve already seen const float PI = 3.14;that creates a float that cannot be changed • We can also create const objects const Time noon(12, 0, 0); • noon is not modifiable
const member functions • Not all member functions modify the object • Accessors • Others later • And so should be declared ‘const’ int GetHour ( void ) const; • The compiler doesn’t “know” that GetHour( ) doesn’t modify the Time object
(non-)const objects and(non-)const member functions • Rules of engagement: • const member functions may be invoked for const and non-const objects • non-const member functions can only be invoked for non-const objects • you cannot invoke a non-const member function on a const object • Constructors and Destructors may not be const
Modified Time class Time { public: Time (int h = 0, int m = 0, int s = 0 ); void InitTime (int h, int m, int s); void PrintMilitary ( void ) const; void PrintStd ( void ) const; void Increment ( void ); …..
Modified Time (cont’d) // mutators void SetHour (int h); void SetMinute (int m); void SetSecond (int s); // accessors – should be const int GetHour (void) const; int GetMinute (void) const; int GetSecond (void) const;
Modified Time (cont’d) private: int hour; int minute; int second; };
int main ( ) { Time t1 (2, 4, 7); const Time noon (12); cout << “Initial Military Time for t1 is :” ; t1.PrintMilitary ( ); // okay cout << endl; cout << “Noon in Military Time:” noon.PrintMilitary ( ); // okay cout << endl; cout << “Increment Noon:” ; noon.Increment ( ); // compiler error cout << endl; }
Non-member functions should have const reference parameters wherever possible • Rules of engagement: • Non-const objects may be passed to const and non-const arguments • Const objects may only be passed to const arguments • Bottom line – you can’t pass a const object to a non-const argument
Non-member PrintTime void PrintTime (Time& t) {cout << t.GetHour( ) << “:”; cout << t.GetMinute( ) << “:”; cout << t.GetSecond( ); }
Calling PrintTime void PrintTime (Time& t); • Callable using t1 – PrintTime ( t1 ); • Not callable with noon – PrintTime (noon); • Why the difference?
A better PrintTime • Since PrintTime( ) doesn’t modify the Time object passed to it, the argument should be const void PrintTime (const Time& t) • Doing so doesn’t change the code, but now does allow noon to use the function PrintTime (noon);
A subtlety • What happens if ‘noon’ is passed to the new PrintTime ( ) function, but the accessors are not const?
Composition • Sometimes objects are used as members of other objects. For example, an AlarmClock class may include a Time object. • This is known as “composition” or “aggregation”. • Member objects are constructed automatically • A common form of code reuse.
AlarmClock class AlarmClock { public: AlarmClock ( ); void SetAlarm (int h, int m, int s); . . . private: . . . void ring( ) const; Time currentTime; const Time alarmTime; }
“this” and that • Every object has access to it’s own address through a pointer called this. • The this is implicitly used to reference both data members and member functions of an object… it can also be used explicitly. • This is passed implicitly as the first argument of every (non-static) member function
A “this” example // should have error checking void Time::SetMinute (int m){ this->minute = m;} • More valuable later
Dynamic Memory Allocation • In C we used malloc int *intp; intp = (int *)malloc (sizeof(int) ); • In C++ we use new int *intp; intp = new int;or intp = new int (7);
Allocating Dynamic Arrays • Again, in C we used malloc: int *ip2; int *ip2 = malloc (50 * sizeof(int)); • In C++ we use new and the size int *ip2 = new int[10];
Freeing Dynamic Memory • In C we used free free (intp); // for a single int free (ip2); // or an array • In C++ we use delete delete intp; // for a single int delete [ ] ip2; // for an array
A simple class that uses dynamic memory Class Array { public: Array (int size = 100); void putElement (int x); int getElement (void); . . . . private: int *theArray;}
Array Constructor • Allocate the memory in the constructor Array::Array (int size) {theArray = new int [size]; }
The Array Destructor • Free the memory in the destructor Array::~Array ( ) {delete [ ] theArray; }
Good Programming Practices • Use const wherever possible • Declare member functions that do not change the object as const • Avoid friends • Use member initialization lists • Allocate dynamic memory only in the constructor • Delete dynamic memory only in the destructor