. Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u...

37
. Copying, casting, and more
  • date post

    21-Dec-2015
  • Category

    Documents

  • view

    213
  • download

    0

Transcript of . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u...

Page 1: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

.

Copying, casting, and more

Page 2: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Example: MyString

Lets put our knowledge of C++ classes to use

Define a class to represent a string Replace all the calls to strdup, strcmp, …

with methods that are clearer and handle memory allocation

[See MyString.h MyString.cpp]

Page 3: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Are we done yet?

Using MyString we can now write code

For example

MyString str1(“Foo”);

MyString str2(“Bar”);

if( str1 > str2 )

str1 = str2; // Whoa! what does this do?

Page 4: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Few Words on Copy…

What does the assignment str1 = str2 do?

High-level view: “=“ is an operator (like “+”) The commend specified here can be written(operator =)(str1,str2)

The compiler searches for a function (operator =) with arguments of type MyString

Function name Arguments

Page 5: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

operator =

For built-in types, the language behaves as though there are functions:int& operator=(int&, int);

double& operator=(double&, double);

This is why we can write:int a, b;

(a = b = 5)++;

// equivalent to: b = 5; a = b; a++;

Page 6: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

What about classes?

The same operator for a class X would have the type signatureX& X::operator=(X const& );

Why X const& argument?

To ensure that the right-hand side of copy does not change (why ref? later on)

The X& return type? To allow for x = y = z like built-in types

Page 7: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

MyString Revisited

We never defined MyString::operator= Why our example compiles?

The compiler defines default instantiation of operator=

This happens for every class for which the programmer did not define his own operator=

Saves unneeded work for many classes

Page 8: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Default operator=

The default operator= copies all data members of the class

In our case, the result isMyString&

MyString::operator=(MyString const& rhs)

{

m_length = rhs.m_length;

m_string = rhs.m_string;

return *this; // return reference to

// current object

}

Page 9: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Example Revisited

void boringExample()

{

MyString str1(“Foo”);

MyString str2(“Bar”);

if( str1 > str2 )

str1 = str2;

}

Problem! A memory location is deleted twice Memory leak

m_stringstr1:

m_stringstr2:

“Foo”

“Bar”

str1 constructorstr2 constructorstr1.operator=(str2)str1 destructorstr2 destructor

Page 10: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

The fix?

Define our own operator=MyString&

MyString::operator=(MyString const& rhs)

{

delete [] m_string;

m_length = rhs.m_length;

init( rhs.m_string );

return *this;

}

Page 11: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Is This Solution Water Tight?

What if a programmer writesMyString str(“foo”);

str = str; // senseless, but legal!

What happens? delete str.m_string allocate a new str.m_string copy this string onto itself…

Page 12: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Checking for Self-copy

Add another check at the beginning of the procedure

MyString&

MyString::operator=(MyString const& rhs)

{

if( this == &rhs )

return *this;

Page 13: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Are We Out of The Woods?

Consider the following codevoid doNothing( MyString S )

{

}

void anotherBoringExample()

{

MyString str(“foo”);

doNothing(str);

}

What is wrong with this picture?

Page 14: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Copy Constructor

What happens when we call DoNothing(str) ? A new MyString object is created on the stack This object needs to be constructed It also needs to copy the value of str

Copy constructor:

MyString::MyString(MyString const& init);

Page 15: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Copy Constructor This constructor is also called when initializing

a new object

MyString str2 = str1;

is equivalent to writing

MyString str2(str1);

In both cases the compiler calls copy constructor

Page 16: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Default Copy Construct

Same as with operator= If not specified, default instantiation is by

copying all data members Constructing each one with the value of the

matching field in source

In our example:

MyString::MyString(MyString const& rhs)

: m_length( rhs.m_length ),

m_string( rhs.m_string )

{}

Page 17: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Example Revisited

void doNothing( MyString S )

{

}

void anotherBoringExample()

{

MyString str(“foo”);

doNothing(str);

}

Problem! str.m_string is deleted by the destructor

Page 18: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Fix?

MyString::MyString(MyString const& rhs)

{

m_length = rhs.m_length;

init( rhs.m_string );

}

Page 19: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Lessons

If a class manages memory, then Define you own operator= and copy

constructor Remember to copy all data members Make sure to check for self-copy Remember that operator= returns a

reference to the object

Page 20: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Disallowing Copy

Some times we want to create classes in which object cannot be copied Large objects, such as a database “One time” data structure …

How do we ensure that object from this class are not copied?

Page 21: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Disallowing Copy

Solution #1: Do not define operator= and copy constructor

Problem: Compiler will define default versions This is not what we want…

Page 22: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Disallowing Copy

Solution #2: generate runtime error

X& operator=(X const& x )

{

assert(false);

return *this;

}

Caveat: Problems shows up very late in the

development process…

Page 23: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Disallowing Copy

Solution #3: Define operator= as privateclass X {

private:

X& operator=(X const&);

};

Cannot be called (compilation error) from outside methods of X

Page 24: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Copy & Inheritance

class Base {

private:

double m_x;

int m_a;

};

class Derived

: public Base {

private:

double m_z;

};

Base a;

Derived b;

a = b;

default copy will

m_x

m_a

a:

m_x

m_a

m_z

b:

Page 25: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Copy & Inheritanceclass A { public: virtual void f1(); virtual void f2(); int m_a;};

class B: public A { public: virtual void f1(); virtual void f3(); void f4();

int m_b;};… A a; B b; a = b;

class A { public: virtual void f1(); virtual void f2(); int m_a;};

class B: public A { public: virtual void f1(); virtual void f3(); void f4();

int m_b;};… A a; B b; a = b;

<vtbl>

m_a

m_b

b:<vtbl>

m_a

a1:

VTBLs

f1

f2

f3

f1

f2

A

B

Page 26: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Function Resolution

With overloading, we can have several functions with the same name

How does C++ know which function to call?

Page 27: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Example

int square( int x );double square( double x );

In C, we get error: “conflicting types for ‘square’”

There can only be one function called square

In C++ these lines do not cause an error The two functions are considered different

declarations

Page 28: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Function Resolution

How does C++ determine which function to call?

Lets check [resolution.cpp]

Page 29: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Function Resolution

In general, upon seeing the statement

foo(x);

The compiler searches for a function foo with argument types that match x

or a function foo with argument types that can be

casted to from the type of x

Page 30: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Function Resolution

int square( int x );

double square( int x );

This does not compile, why? Based on return type alone, we cannot

distinguish between the functions. It is possible that we will encounter code like

square( 5 );

Page 31: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Function Resolution

How does C++ determine whether it can cast type A to type B ?

Standard Casts: int double, char int, etc.

Tailored Casts: casts introduced by the programmer

Page 32: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Example

class MyClass {

public:

MyClass(int i);

};

The constructor is viewed as a way of taking an integer an making it into a MyClass object

Page 33: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Example

void foo( MyClass x );

int i;

foo(i); // What happens here?

The compiled code for the last line is eq. to

{

MyClass tmp(i);

foo(tmp);

}

Page 34: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Implicit Cast

This feature is useful for seamless operations For example, MyString has a cast from char* We can use “<String>” in calling functions

that expect MyString

MyString str;

if( str == “foo” )

Page 35: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Implicit Castclass IntArray {

public:

IntArray(int size); // constructor

bool operator==(IntArray const& rhs) const;

int operator[](int i) const;

};

IntArray A(5), B(5);

for( i = 0; i < 5; i++ )

if( A == B[i] ) // oops! should have been A[i] == B[i]

This creates a new temporary IntArray of size B[i] !!!

Page 36: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Explicit Keyword

A directive to compiler not to use constructor in implicit casts

class IntArray {

public:

explicit IntArray(int size); // constructor

};

Page 37: . Copying, casting, and more. Example: MyString u Lets put our knowledge of C++ classes to use u Define a class to represent a string u Replace all the.

Lessons

C++ can create temporary objects “behinds the scenes”

To avoid this: Use explicit keyword for constructors Pass objects by reference

void foo( MyClass const& Obj );

instead ofvoid foo( MyClass Obj );

Declare a private copy constructor