Presentation is loading. Please wait.

Presentation is loading. Please wait.

Yan Shi CS/SE 2630 Lecture Notes

Similar presentations


Presentation on theme: "Yan Shi CS/SE 2630 Lecture Notes"— Presentation transcript:

1 Yan Shi CS/SE 2630 Lecture Notes
3. Big3 Yan Shi CS/SE 2630 Lecture Notes

2 The Big Three In C++, classes come with 3 special functions that are already written for you, known collectively as the big three. In many cases, you can accept the default behavior of these function. By default: Destructor: calls the destructors of all members/release all primitive members. Copy Constructor: applies copy constructors/assignments to each data member operator=: applies assignment operator to each data member Example: class Person { private: char name[31]; Date birthday; };

3 Example: default Default Big3! class Cell { private: int value;
public: int Get() return value; } void Set( int x ) value = x; }; void main() { Cell a; a.Set(2); Cell b = a; Cell c(a); b.Set(8); c = b; a.Set(5); cout << a.Get() << " " << b.Get() << " " << c.Get() << endl; } Default Big3!

4 Example: Default Big3 Cell( const Cell & c ) { value = c.value; } ~Cell(){ } Cell& operator=( const Cell &rhs ) if ( this != & rhs ) // must check for self assignment! value = rhs.value; return *this; // return a reference to myself operator=: return a reference to allow operator chaining. assignment is right-associative! int a, b, c; a = b =c = 4; // a = ( b = ( c = 4 ); It is important to return a non-const reference because primitive types allow operations like: (a = b ) = c; The rule of thumb is, "If it's good enough for ints, it's good enough for user-defined data-types." this is a pointer to the object that the member function is being called on. a = b is the same as a.operator=(b)

5 Pointers and the Big Three
If a class contains pointers, we may have problem with defaults!! we must delete pointers by ourselves. The copy constructor and operator= only do “shallow copying”: giving us two class instances with a pointer to the same object. we expect “deep copying”  We need to implement the Big Three by ourselves! Example: class Person { private: char * name; Date birthday; };

6 Example: With Pointer Member
class Cell { private: int *value; public: int Get() return *value; } void Set( int x ) *value = x; }; void main() { Cell a; a.Set(2); Cell b = a; Cell c(a); b.Set(8); c = b; a.Set(5); cout << a.Get() << " " << b.Get() << " " << c.Get() << endl; } Is this code correct? No! value is not initialized!

7 Example: With Pointer Member
class Cell { private: int *value; public: Cell ( int x = 0 ) value = new int(x); } int Get() return *value; void Set( int x ) *value = x; }; void main() { Cell a; a.Set(2); Cell b = a; Cell c(a); b.Set(8); c = b; a.Set(5); cout << a.Get() << " " << b.Get() << " " << c.Get() << endl; } Function overloading: If there is no parameter x, assume x = 0.

8 Example: With Pointer Member
class Cell { private: int *value; public: Cell ( int x = 0 ) value = new int(x); } int Get() return *value; void Set( int x ) *value = x; }; void main() { Cell a; a.Set(2); Cell b = a; Cell c(a); b.Set(8); c = b; a.Set(5); cout << a.Get() << " " << b.Get() << " " << c.Get() << endl; } // What is b’s value? // Will b and c’s values change? // Is there any memory leak?

9 Example: Implement Big3
Cell( const Cell & c ) { value = new int( *c.value ); } ~Cell(){ delete value; } Cell& operator=( const Cell &rhs ) if ( this != & rhs ) // must check for self assignment! *value = *rhs.value; return *this; // return a reference to myself The main semantic difference between int* and int& is that the former allows passing of NULL or uninitialized values, and the latter does not.  member access operator “->” only applies to pointers!

10 Destructor Destructor is called when an object goes out of scope.
A class can have only one destructor without any parameters. When there are pointer data members in a class, you should implement your own destructor to delete all dynamically allocated memory space other operations as needed

11 Operator Overloading In C++, you can give special meanings to operators when they are used with user-defined classes. = (assignment operator) + - * (binary arithmetic operators) += -= *= (compound assignment operators) == != > < >= <= (comparison operators) Implement operator overloads by providing special member-functions in your classes.

12 Assignment Operator= class MyClass { public: ...
// the = operator don’t change the rhs, only the lhs // return a reference to allow operator chaining // why not returning const MyClass&? // to enable operations such as ( a = b ) = c // "If it's good enough for ints, // it's good enough for user-defined data-types." MyClass & operator=(const MyClass &rhs); } MyClass a, b, c, d; b = a; // Same as b.operator=(a); d = c = b = a; // assignment is right-associative. // same as d = ( c = ( b = a)));

13 Assignment Operator= The typical sequence of operations:
MyClass & operator=(const MyClass &rhs) { //0. Self assignment check! //1. Deallocate any memory that MyClass is using internally //2. Allocate some memory to hold the contents of rhs //3. Copy the values from rhs into this instance //4. return *this; } the member function needs to return a reference to the object. So, it returns *this, which returns what this points at (i.e. the object). (In C++, instances are turned into references, and vice versa, because references are treated as alternative names for instances, so C++ implicitly converts *this into a reference to the current instance.)

14 Assignment Operator= You must check for self assignment!!!
What happens if we do: MyClass obj; obj = obj; obj will first release any memory it holds internally.  This completely messes up the rest of the assignment operator's internals.

15 Assignment Operator = Self assignment checking:
MyClass & operator=(const MyClass &rhs) { // Check for self-assignment! if (this != &rhs) // Same object? ... // Deallocate, allocate new space, copy values... } return *this;

16 Compound Assignment Operators += -= *=
// similar prototype as operator= MyClass & MyClass::operator+=(const MyClass &rhs) { ... // Do the compound assignment work. return *this; } MyClass a, b; ... b += a; // Same as b.operator+=(a); Compound assignment operators are destructive operators: they update or replace the values on lhs of the assignment. In general, beware of self-assignment as well.

17 Binary Arithmetic Operators + - *
Binary arithmetic operators don’t modify either operand, but actually return a new value from the two arguments Use the compound operator (+=) implementation to implement binary (+) operator! // pass a const reference, return a const MyClass value const MyClass MyClass::operator+(const MyClass &other) const { MyClass result = *this; result += other; return result; } MyClass a, b, c; ... c = a + b; // Same as c = a.operator+(b); //return MyClass(*this) += other; same as: MyClass result = *this; // Make a copy of myself. Same as MyClass result(*this); result += other; // Use += to add other to the copy. return result; Why returning const MyClass? We need to return a MyClass object We don’t want to allow (a + b) = c;!

18 Comparison Operator == and !=
== and != return true or false usually implement == first, then use == to implement != // pass a const reference, return a bool value bool MyClass::operator==(const MyClass &other) const { // compare the values and return a bool result } bool MyClass::operator!=(const MyClass &other) const { return !(*this == other); } MyClass a, b; ... if ( a == b )// Same as if ( a.operator==(b) )

19 Overloading << and >>
// return a reference for ostream to allow recursive << // use friend keyword to access the private members of MyClass friend ostream& operator<<(ostream& out, const MyClass & m) { out << ...what to print m...; return out; } friend istream& operator>>(istream& in, MyClass & m) // whatever code to read m: use in instead of cin return in; MyClass a,b; cin >> a >> b; cout << a << b; it is important to make operator overloading function a friend of the class because it would be called without creating an object.

20 Friend Functions A friend function is a function that is not a member of a class but has access to the class's private and protected members.  friend functions are not considered as class members; they are not in the class's scope, and they are not called using the dot notation.   A friend function is declared by the class that is granting access. The friend declaration can be placed anywhere in the class declaration. It is not affected by the access control keywords.

21 Operator overloading restrictions
Cannot overload scope resolution operator :: member access operator ., .* ternary conditional operator ?: Cannot create new operators

22 After class exercise: How to implement a growable array?
Hint: define a growable array class; overload operator[] How to overload operator++?


Download ppt "Yan Shi CS/SE 2630 Lecture Notes"

Similar presentations


Ads by Google