1 / 49

EE4E. C++ Programming

EE4E. C++ Programming. Lecture 2 Classes. Contents. Introduction User defined data types Classes and encapsulation Implementation/interface Classes and objects Creating/initializing objects – constructors Destroying objects – destructors Other features of classes. Introduction.

jacob
Download Presentation

EE4E. C++ Programming

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. EE4E. C++ Programming Lecture 2 Classes

  2. Contents • Introduction • User defined data types • Classes and encapsulation • Implementation/interface • Classes and objects • Creating/initializing objects – constructors • Destroying objects – destructors • Other features of classes

  3. Introduction • Classes are the core of C++’s support for object oriented programming • They allow the programmer to create abstract data types in a similar way that struct does in C • However the C++ class also supports encapsulation whereas struct does not • Encapsulation allows the programmer to hide details about the implementation • First we will review the struct construct

  4. User defined data types • C (and C++) allow user defined data types to be created using the struct construct • For example, we could create a Date data type to represent dates struct Date { int d; int m; int y; };

  5. We could create variables (objects) of the Date data type as well as writing functions that operate on these objects extern void set_date(Date*, int, int, int); extern void print_date(const Date*); void main() { Date* date = new Date; set_date(date,28,8,2003) print_date(date); }

  6. In C++, we can include the functions as part of the struct declaration so they become member functions • This means we don’t have to pass the objects as arguments into the functions struct Date { int d; int m; int y; void set(int,int,int); void print(); };

  7. void Date::set(int dd, int mm, int yy) { d=dd; m=mm; y=yy; } void Date::print() { printf(“Day, month, year = %d %d %d ”, d, m, y); } • The member functions are defined using the :: operator as follows :

  8. Finally Date objects can be created and member functions called as follows : • Note that member functions are called through the object (variable) name void main() { Date today; today.set(12,8,2003) today.print(); }

  9. Classes and encapsulation • Classes in C++ are similar and have similar syntax and uses as structures in C with one key difference • They support the idea of encapsulation • The implementation of the class is hidden from the interface to the class • This is achieved through the use of public and private member access specifiers

  10. class Date { private: int d; int m; int y; public: void set(int,int,int); void print(); void advance(); }; • We can define a Date class as follows :

  11. An additional member function advance() has been added which advances the date by one day • Apart from that, this has the same functionality as the Date structure • The key difference is the separation of the class into private and public • This separation underpins the ideas behind encapsulation (or implementation/interface)

  12. Key point • Only public member functions of Date can access private members of the class • Enforced by rules of the language • If we try to access a private class member from outside a public member function, a compilation error is triggered

  13. Implementation of Date::set() is as follows • Accesses Date::d, Date::m, Date::y which is OK as it’s a public member function void Date::set(int dd, int mm, int yy) { d=dd; m=mm; y=yy; }

  14. int get_year(Date date) { return date.y; // Error! } int main() { Date today; today.d=28; // Error! today.m=8; // Error! today.y=1998; // Error! } • The following is illegal code • This is an attempt to access a private class member from outside a public member function

  15. class Date { private: int d; int m; int y; public: void set(int,int,int); void print(); void advance(); int day() {return d;} // access function int month() {return m; } // access function int year() {return y;} // access function }; • In order to access the private class members Date::d, Date::m, Date::y, we have to provide public member access functions

  16. You may wonder (quite rightly!) whether this is an undue computational overhead • In order to access a private class member, we have to go through an additional function call • However, access restriction of the classes private members is key to encapsulation • Implementation/interface

  17. Implementation/interface • We can justify the sub-division of a class into private and public by considering the idea of the implementation of the class and the interface to the class • The implementation of the class is represented by the private class members and public member function bodies (which use the private members) • The interface to the class is represented by the public member functions headers

  18. Date private int d int m int y Implementation public void set() void print() void advance() int date() int month() int year() Interface

  19. Changing the implementation of Date • Suppose we decide to change the implementation of Date and represent the date internally in the Julien format • This represents the number of days since 1/1/1900 from which the current day, month and year can be computed algorithmically

  20. class Date { private: long julien; // Number of days since 1/1/1900 public: void set(int,int,int); void print(); void advance(); int day() {// returns d} // access function int month() {// returns m } // access function int year() {// returns y} // access function };

  21. The key point is that public member function body implementations need to change to reflect the changed private members • However, the public member function headers remain the same • These represent the interface to the Date class as seen by application programs using the class

  22. Date :: day() { // complicated algorithm } Date :: month() { // complicated algorithm } Date :: year() { // Simple algorithm (taking into account leap years) } Date::advance() { julien++; }

  23. Key point • Because of encapsulation, applications using the Date class will not change as they only interact with the class through public member function calls • This leads to more robust extendible systems

  24. For example, some external function weekend() will still be correct even after the changes to Date • The function interacts with Date through the public member function day() int weekend(Date date) { // Returns true if the date falls on a weekend return ((date.day()==0)||(date.day()==6)); }

  25. Classes and objects • Its important to be clear about the distinction between classes and objects • It may seem obvious but it does cause confusion • Essentially an object is an instantiation of a class • We can create many objects of the same class

  26. Date date; date.set(14,4,2003) Date another_date; another_date.set(15,4,2003); • We can create several date objects as follows : Date date Apr 14, 2003 Date another_date Apr 15, 2003

  27. We have 1 class • Date • We have 2 objects • date • another_date • Typically class names will start with upper case and object names will start with lower case

  28. Creating/initializing objects – constructors • Objects can be created and initialized by declaring special public member functions called constructorswith the same name as the class • A nice feature of constructors is that function overloading can be used so that objects can be initialized in different ways

  29. class Date { private: int d,m,y; public: Date(); // constructor Date(int,int,int); // constructor Date(char *); // constructor void set(int,int,int); void print(); void advance(); int day() {return d;} // access function int month() {return m; } // access function int year() {return y;} // access function };

  30. Date::Date() { // default construcotr } Date::Date(int dd, int mm, int yy) { d=dd; m=mm; y=yy; } Date::Date(char* date_string) { // Parse the string and assign to d, m, y } • The implementation of the constructors are as follows :

  31. We can now create and initialize objects as follows : Date tomorrow; // Date() called Date today(1,9,1998); // Date(int,int,int) called Date yesterday("31st August 1998"); // Date(char*) called

  32. Note that the constructor is automatically called when an object is declared • It doesn’t have to be initialized (although it is usually good practice to do so) • However, the default constructor must be present if we wish to create uninitialized objects • Note also that we can create objects dynamically and this also involves calling a constructor Date* today = new Date(1,9,1998); today->advance();

  33. Destroying objects – destructors • Destructors are member functions which are called automatically (see later) in order to delete an object and release all of the memory taken by that object • Unlike Java, C++ has no automatic garbage collection • For a simple class like Date, no dynamic allocation of private member variables has taken place so the compiler can delete Date objects by simply deleting each private member variable

  34. For classes where private members have been dynamically allocated, we must implement the destructor in order for the object to be completely deleted class myClass { private: char* message; int message_length; public: myClass(char* m, int len); // constructor ~myClass(); // destructor };

  35. myClass::myClass(char* m, int len) { message_length=len; message=new char[len]; strcpy(message,m); } myClass::~myClass() { delete[] message; }

  36. Destructors are called automatically when : • The delete operator is called for a dynamically created object • An automatically created object goes out of scope • The program (main) (or a function) terminates for a statically created object • The destructors for globally defined objects are called last of all

  37. Other features of classes • We will look at a few other features of classes • this self-reference • Friends • Static class members

  38. Self-reference - this • Each (non-static) member function has a access to a pointer to the instantiated object from which the member function was called (!!) • So, for example, in our Date class, member functions have access to a (constant) pointer of type Date*

  39. Date private int d int m int y public . . void advance() { // access to this } .

  40. The following re-implementation of advance() makes a copy of a Date object using a de-referenced this but moved on 1 day Date Date::advance() { Date d=*this; // make a copy d.julien++; return d; } Date d(1,9,1998); Date new_d=d.advance();

  41. Thus, a completely new initialized Date object is produced Date new_d 2/9/98 Date d 1/9/98

  42. Friends • A function or a class can be made a friend of another class • This means that the function or class members can access the private members of the class • Using the friend keyword in a class declaration allows encapsulation to be broken and should be used carefully

  43. class X { . friend int func(); friend class Y; . }; • This declaration allows func() and all of Y’s member functions to access the private parts of class X • Note that it is the designer of class X who specifies the friend relationships

  44. class Date { private : int d,m,y; public : Date(int,int,int); // constr. . friend int weekend(Date); }; int weekend(Date date) { return ((date.d==0)||(date.d==6)); // OK! }

  45. Static class members • Each object has its own copy of all non-static date members of a class • A static class members belongs to the class • There is only 1 class wide copy • Useful for maintaining class wide information • static class data members exist even if an object hasn’t been instantiated

  46. static class members still have private, public privileges • Only static public member functions can access static private members if an object has yet to be instantiated • In this case the member function is accessed through the class name using the :: operator • Once an object has been instantiated, static members can be accessed through non-static public member functions also • static class members must be initialized once and once only before use

  47. A static class member num_objects can be used to keep a track on the number of objects of a certain class that have been created class myClass { private : static int num_objects; public : myClass() { num_objects++;} static int get() { return num_objects;} };

  48. int myClass::num_objects=0; // Initialize static void main() { printf(“num objects so far = %d ”, myClass::get()); // prints 0 myClass m1; myClass m2; myClass m3=new myClass(); printf(“num objects so far = %d ”, myClass::get()); // prints 3 }

  49. And finally …….. • The key message in this lecture is encapsulation and implementation/interface separation • This leads to self-contained software units – classes – which are the basis of object oriented programming • Object oriented applications comprise a set of objects, interacting through their class interfaces • The next lecture looks at inheritance and polymorphism which allow for flexible object behaviour, a key element of OOP

More Related