CS212: Object Oriented Analysis and Design Lecture 10: Copy constructor
Recap of Lecture 9 Function Overloading Name Mangling Resolution of name and type Copy constructor
Outline of lecture 10 Copy constructor Operator overloading Unary operator Operator chaining
Pointers in C++ Pointers in C++ is a more strongly typed language C doesn’t let you casually assign a pointer of one type to another It does allow you to accomplish this through a void* bird* b; rock* r; void* v; v = r; b = v;
Recap of reference A reference must be initialized when it is created. Once a reference is initialized to an object, it cannot be changed to refer to another object. You cannot have NULL references. Must be careful while returning reference from a function !! Should not refer to unknown memory.
Constant Reference The function does modify the outside argument. Making the argument a const reference will allow the function to be used in all situations. For built-in types, the function will not modify the argument For user-defined types, the function will call only const member functions, won’t modify any public data members. Temporary objects are always constant
Argument-passing guidelines Normal habit when passing an argument to a function should be to pass by const reference. There are concerns other than efficiency To pass an argument by value requires a constructor and destructor call If the arguments are not going to be modified : pass by const reference
Passing and returning by value Declare a function and make a function call, how does the compiler know how to pass and return those variables? Equivalent assembly code int f(int x, char c); int g = f(a, b); push b push a call f() add sp,4 mov g, register a
Passing and returning large objects The entire contents of B is pushed on the stack The address of B2 is pushed before making the call Constraints on the compiler when it’s making a function call. struct Big { char buf[100]; int i; long d; } B, B2; Big bigfun(Big b) { b.i = 100; // Do something return b; } int main() { B2 = bigfun(B); }
Function-call stack frame 1.Pushes all the arguments on the stack 2.Makes the call 3.Provide storage for the function’s local variables Function arguments Return address Local variables Re-entrancy
Functions in C and C++ support interrupts: re-entrant They also support recursive calls Return values on the stack?? Allocating the extra storage on the stack for the return values before calling the function. Push the address of the return value’s destination on the stack as one of the function arguments, The function copy the return information directly into the destination.
Bitwise copy and its issue Class: Student NameRollMarks Sumit925 Class: Student NameRollMarks Sumit925 A B= A
Bitwise copy and its issue Class: Student NameRollM1M2M3M4 Sumit A B= A Class: Student NameRollM1M2M3M4 Sumit
Bitwise copy and its issue Class: Student NameRoll*Marks Sumit90xABC Class: Student NameRoll*Marks Sumit90xABC A B= A
Create object from an existing object One of the more important forms of an overloaded constructor is the copy constructor. Defining a copy constructor can help you prevent problems that might occur when one object is used to initialize another. When we copy? Initialize Pass as argument Return as parameter
Deep vs Shallow copy Copy constructor is called only for initializations For assignment ? Operator overload ??
Operator overloading Compiler sees an expression consisting of an argument followed by an operator followed by an argument, it simply calls a function. An operator is simply a function call with a different syntax. There must be a previously declared function to match that operator Operator overloading is just “syntactic sugar,” which means it is simply another way for you to make a function call.
Is the knowledge about operator wrong ? Maybe everything they know about operators in C is suddenly wrong Operators for built-in types won’t suddenly start working differently Overloaded operators can be created only where new data types are involved 1 << 4; << 1; won’t suddenly change its meaning won’t suddenly start working.
Operator overloading Specify more than one definition for an operator in the same scope Declared (or defined) previously in the same scope The compiler determines the most appropriate definition to use Overload resolution Redefine or overload most of the built-in operators available
We are already overloading Inserters ( >) A stream is an object that formats and holds bytes. int i; cin >> i; float f; cin >> f; char c; cin >> c; char buf[100]; cin >> buf;
Operator overloading Overloaded operators are functions with special names The overloaded function will perform relative to the class upon which it will work The keyword operator followed by the symbol for the operator being defined Operator functions can be member or non-member of a class Non-member operator function : friend functions
Creating a Member operator function The general form of such a function is Ret-type classname::operator#(arg-list){ //operations } // Overload + for loc. loc loc::operator+(loc op2) Demonstration
Can we overload all operators +-*/%^ &|~!,= <><=>=++-- <<>>==!=&&|| +=-=/=%=^=&= |=*=<<=>>=[]() ->->*newnew []deletedelete [] ::.*.?:
Parameter passing to operator function Operator function Global Unary (1) Binary (2) Member Unary (0) Binary (1) The number of arguments in the overloaded operator’s argument list depends on two factors
Restrictions Cannot combine operators that currently have no meaning Cannot change the evaluation precedence of operators Cannot change the number of arguments required by an operator
Overloading Unary Operator Takes just one operand Takes no argument Example: Increment (++) and decrement(--) operator Unary minus (-) operator The logical not (!) operator The unary operators operate on the object for which they were called
Operator chaining Assignment is right-associative In order to support operator chaining, the assignment operator must return some value The value that should be returned is a reference to the left- hand side of the assignment. But should this reference be a const or nonconst? int a, b, c, d, e; a = b = c = d = e = 42;
Self assignment MUST CHECK FOR SELF-ASSIGNMENT !! Especially important when your class does its own memory allocation MyClass& MyClass::operator=(const MyClass &rhs) { // 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 } MyClass mc;... mc = mc;
How to recover self assignment There are many ways to answer the question Are these two instances the same? Just compare the two objects' addresses MyClass& MyClass::operator=(const MyClass &rhs) { if (this != &rhs) {... // Deallocate, allocate new space, copy values... } return *this; }
Assignment operator The guidelines for the assignment operator are: Take a const-reference for the argument (the right-hand side of the assignment). Return a reference to the left-hand side, to support safe and reasonable operator chaining. (Do this by returning *this.) Check for self-assignment, by comparing the pointers (this to &rhs).
Thank you Next Lecture: Operator Overloading-II