Presentation is loading. Please wait.

Presentation is loading. Please wait.

Classes Separating interface from implementation

Similar presentations


Presentation on theme: "Classes Separating interface from implementation"— Presentation transcript:

1 Classes Separating interface from implementation
Place the class declaration in a header file (.h) to be included (via #include) in each file that uses the class. This means that several files of the same project may all #include the header file. However, the compiler should only process it once. Conditional compilation allows code to be included or omitted based on certain conditions. We can use the following directives for conditional compilation: #ifdef, #ifndef, #else, #endif, #define

2 Classes Special member functions: constructors
have the same name as the class are used to initialize the data members are invoked automatically when class objects are created do not have a return type destructor has the same name as the class preceded by a tilde (~) is used to perform housekeeping (such as memory deallocation) when a class objects is destroyed is invoked automatically when class objects are destroyed does not have arguments does not have a return type is ESSENTIAL when there are pointer data members

3 Classes When a data member is a pointer, the constructor must allocate space for it and the destructor must deallocate space. Example: class MemberInfo { char *name; int age; public: MemberInfo(char *initname = ""i, int initage = 0) { name = new char[strlen(initname)+1]; strcpy(name, initname); age = initage; } ~MemberInfo() { if (name != NULL) delete [] name; };

4 Copy constructor There are certain situations when a copy of an object must be made: when passing the object by value when returning an object Furthermore, we want to be able to initialize an object by another object. e.g. Creating a copy of an object is the job of the copy constructor. A special kind of constructor that takes as argument an object of the same type as the class. MemberInfo president ("John Smith", 50); // Now declare clone, a new MemberInfo whose data members // should have the same values as those for president: MemberInfo clone(president);

5 Copy constructor If a copy constructor is missing, the compiler creates a default one performs member-by-member copying. A default copy constructor for the MemberInfo class would look like this: As we will see, this is INCORRECT! Consider the following piece of code: MemberInfo (const MemberInfo& init) { name = init.name; age = init.age } MemberInfo *president = new MemberInfo ("Smith", 50); MemberInfo clone(*president); delete president; president = NULL; continue on next slide...

6 Copy constructor & pointers
1: MemberInfo *president = new MemberInfo ("Smith", 50); president 'S' 'm' 'i' 't' 'h' '\0' 50 2: MemberInfo clone(*president); Let's look inside the copy constructor: name = init.name; age = init.age president 'S' 'm' 'i' 't' 'h' '\0' 50 clone 50 continue on next slide...

7 Copy constructor & pointers
3: delete president; president = NULL; president freed memory clone 50 president and clone should be independent objects. Modifying one should not affect the other. When pointers are involved, the copy constructor must explicitly allocate space and copy the appropriate value. See the next slide for a correct version of the copy constructor.

8 Copy constructors & pointers
MemberInfo (const MemberInfo& init) { name = new char[strlen(init.name)+1]; strcpy(name, init.name); age = init.age }

9 operator= A problem similar to that of the copy constructor appears when we use assignments. If me and president are two MemberInfo objects, then by default, me = president; will perform a member-by-member assignment. To avoid the problem, the assignment operator must be overloaded by the programmer. Operator overloading = having more than one operator with same name (in the same scope) Example: integers and MemberInfo objects both have the assignment operator defined for them. The operator has the same name, =, but works in different ways depending on the type of the object.

10 operator= think of obj1 = obj2; as being equivalent
to obj1.operator=(obj2); returning a reference to the current object allows chain assignments: obj1 = obj2 = obj3; pass the right-hand-side as a reference but do not allow it to be modified. MemberInfo& operator= (const MemberInfo& rhs) { if ( this == &rhs ) return *this; if ( name != NULL) delete [] name; name = new char[strlen(rhs.name)+1]; strcpy(name, rhs.name); age = rhs.age } the this pointer provides access to an object's own address. this is a C++ keyword.

11 operator= if the right-hand side and the left-hand side
MemberInfo& operator= (const MemberInfo& rhs) { if ( this == &rhs ) return *this; if ( name != NULL) delete [] name; name = new char[strlen(rhs.name)+1]; strcpy(name, rhs.name); age = rhs.age } if the right-hand side and the left-hand side are identical, (e.g. obj1 = obj1) just return a reference to the current object. (Looking ahead: what will happen if we don't perform this check?)

12 operator= Since the current object will be assigned a new
MemberInfo& operator= (const MemberInfo& rhs) { if ( this == &rhs ) return *this; if ( name != NULL) delete [] name; name = new char[strlen(rhs.name)+1]; strcpy(name, rhs.name); age = rhs.age } Since the current object will be assigned a new value, make certain that any space allocated for the current value is properly deallocated.

13 operator= Finally, perform the actual assignment and
MemberInfo& operator= (const MemberInfo& rhs) { if ( this == &rhs ) return *this; if ( name != NULL) delete [] name; name = new char[strlen(rhs.name)+1]; strcpy(name, rhs.name); age = rhs.age } Finally, perform the actual assignment and return a reference to the current object.

14 pointer data members Whenever a class has at least one data member that is a pointer, you MUST write a destructor a copy contructor an overloaded assignment operator


Download ppt "Classes Separating interface from implementation"

Similar presentations


Ads by Google