CS212: Object Oriented Analysis and Design Lecture 10: Copy constructor.

31
CS212: Object Oriented Analysis and Design Lecture 10: Copy constructor

Transcript of CS212: Object Oriented Analysis and Design Lecture 10: Copy constructor.

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 codeint f(int x, char c);

int g = f(a, b);push bpush acall f()add sp,4mov 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

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

Name Roll Marks

Sumit 9 25

Class: Student

Name Roll Marks

Sumit 9 25

A

B= A

Bitwise copy and its issue

Class: Student

Name Roll M1 M2 M3 M4

Sumit 9 25 35 40 38

A

B= A

Class: Student

Name Roll M1 M2 M3 M4

Sumit 9 25 35 40 38

Bitwise copy and its issue

Class: Student

Name Roll *Marks

Sumit 9 0xABC

Class: Student

Name Roll *Marks

Sumit 9 0xABC

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.414 << 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 (<<) and extractors (>>)

• 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

+ - * / % ^

& | ~ ! , =

< > <= >= ++ --

<< >> == != && ||

+= -= /= %= ^= &=

|= *= <<= >>= [] ()

-> ->* new new [] delete delete []

:: .* . ?:

Parameter passing to operator function

Operator functionGlobal

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 youNext Lecture: Operator Overloading-II