Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

45
Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II
  • date post

    21-Dec-2015
  • Category

    Documents

  • view

    226
  • download

    2

Transcript of Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

Page 1: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

Constructors, Destructors, Operator Overloading

CS 1037 Fundamentals of Computer Science II

Page 2: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

2

Some Special Functions...

A. Constructors (to set up an object’s state)

Destructors (to ‘tear down’ an object)

B. Operator Overloading (extending C++)

struct sound { int size; double* samples; sound(); // constructor declaration ~sound(); // destructor declaration};

void operator*=(sound& s, double ratio);

sound make_me_louder;make_me_louder *= 2.0; // now C++ knows what this means

Page 3: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

3

Part A. Constructors, Destructorsstruct point { int x, y; point(); // default-constructor declaration};

point::point() { // default-constructor definition x = 0; y = 0;}

Page 4: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

4

Why Constructors?

• Variables/objects start with random data

• Uninitialized variables huge source of bugs– most objects need initialization before use (dynarray)– some languages force initialization before use (C#)

• Constructors allow consistent, automatic initialization of member variables in C++

void main() { point pos; // uninitialised! draw_circle(pos.x,pos.y);}

pos???? ????x y

Page 5: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

5

Defining a Constructor

• Just define a member function with the same name as the struct/class itselfstruct point { int x, y; point(); // default-constructor declaration};

point::point() { // default-constructor definition x = 0; y = 0;}

void main() { point pos; // call the default-constructor draw_circle(pos.x,pos.y); // draws at (0,0)}

void point();void point::point() {

Omit the void

Page 6: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

6

Defining a Constructor

• Constructors can also take arguments! Allows per-object initializationstruct point { int x, y; point(int ax, int ay); // constructor declaration};

point::point(int ax, int ay) { // constructor definition x = ax; y = ay;}

void main() { point pos(0,0); // call the constructor draw_circle(pos.x,pos.y); }

void point();void point::point() {

Omit the void

Page 7: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

7

A Small Price to Pay

• If constructors defined, they become the only way to initialize (no initializer-lists)// if just point(int,int) constructor...void main() { point p; // ERROR point q(5,10); // OK point r = {5,10}; // ERROR (*)}

(*) This will work in new versions of C++ circa 2011; see Stroustrup’s comments: http://www2.research.att.com/~bs/C++0xFAQ.html#init-list

Page 8: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

8

Multiple Constructors

• Provide whatever makes sense for typestruct point { int x, y; point(); // default-constructor point(int ax, int ay); // a convenient constructor};

point::point() { x = y = 0; }point::point(int ax, int ay) { x = ax; y = ay; }

void main() { point p; // call default-constructor point q(5,10); // call constructor point r(q); // call copy-constructor}

Page 9: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

9

Members with Constructorsstruct rectangle { point a,b; rectangle(); // default-constructor rectangle(point pa, point pb); // constructor rectangle(int l, int t, int r, int b); // constructor};

rectangle::rectangle(){ // calls default-constructor point() on a,b}

rectangle::rectangle(point pa, point pb): a(pa), b(pb) // calls copy-constructor on a,b{}

rectangle::rectangle(int l, int t, int r, int b): a(l,t), b(r,b) // calls constructor point(int,int) on a,b{}

Page 10: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

10

Members with Constructorsstruct rectangle { point a,b; rectangle(); rectangle(point pa, point pb); rectangle(int l, int t, int r, int b);};

void main() { point p(0,0), q(40,80); rectangle r1; // r1 = { {0,0}, {0,0} } rectangle r2(p,q); // r2 = { {0,0}, {40,80} } rectangle r3(0,0,40,80); // r3 = { {0,0}, {40,80} } rectangle r4(r3); // r4 = { {0,0}, {40,80} }

rectangle r5(point(0,0),point(40,80)); // like r2}

Page 11: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

11

Init-Function vs Constructor

struct sound { int size; double* samples;};

// default sound is no soundvoid init_sound(sound& s) { s.size = 0; s.samples = 0;}

void main() { sound snd; init_sound(snd); play_sound(snd);}

struct sound { int size; double* samples; sound();};

sound::sound() { size = 0; samples = 0;}

void main() { sound snd; play_sound(snd);}

==

manual initialization via function automatic initialization

Manual initialization easily forgotten: a classic source of bugs!

Page 12: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

12

Destructors

• Constructors handle ‘birth’ of an object• Destructors handle deeaath

• Special member function that gets called automatically when variable/object dies

void main() { sound snd; // snd is born!!} // snd's scope ended... gone, forgotten, DEAD

struct sound { int size; double* samples; sound(); // constructors must be named 'sound' ~sound(); // destructor must be named '~sound'};

Page 13: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

13

Why Destructors?• Sophisticated objects need to release

internal resources “clean up after themselves”struct sound { int size; double* samples;};

// de-allocate samples arrayvoid destruct_sound(sound& s) { delete[] s.samples;}

void main() { sound beep; load_sound(beep,"beep.mp3"); ... destruct_sound(beep);}

struct sound { int size; double* samples; ~sound();};

sound::~sound() { delete[] samples;}

void main() { sound beep; load_sound(beep,"beep.mp3"); ...}

==

struct sound { int size; double* samples;};

// de-allocate samples arrayvoid destruct_sound(sound& s) { delete[] s.samples;}

void main() { sound beep; load_sound(beep,"beep.mp3"); ... destruct_sound(beep);}

Page 14: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

14

Real Life™ Example

• Destructors can be complicated– e.g. destructor for a real linked-list* class:slist::~slist() { node* n = m_head; while (n != (node*)&m_head) { // loop over list nodes node* prev = n; n = n->next; delete prev; // delete each list item }}

*Not necessarily same destructor used in CS1037 linked list

Page 15: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

15

More Examplesstruct noisy { noisy(); ~noisy();};

noisy::noisy() { cout << "HELLO!" << endl; }noisy::~noisy() { cout << "GOODBYE!" << endl; }

void main() { noisy a,b;}

Page 16: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

16

More Examples – Arrays

void main() { noisy* ptr = new noisy[3];}

void main() { noisy* ptr = new noisy[3]; delete ptr;}

void main() { noisy* ptr = new noisy[3]; delete[] ptr;}

CORRECT

MEMORY LEAK?

MEMORY LEAK

Page 17: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

17

More Examples – Scope

• ‘Noisy’ constructors & destructors good way to teach yourself about variables & their scope.

void main() { noisy a; for (int i = 0; i < 2; ++i) { noisy b,c; }}

You should be able to describe which variable printed which line!

Page 18: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

18

More Examples – Arguments

• Constructor for b didn’t print! Why?– b not initialized by default-constructor noisy()– b initialized by copy-constructor, as copy of a

void func(noisy b) { noisy c;}

void main() { noisy a; func(a);}

Wait... what???

Page 19: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

19

With Copy-Constructor

struct noisy { noisy(const noisy& src); // copy-constructor noisy(); // default-constructor ("HELLO!") ~noisy(); // destructor (“GOODBYE!”)};

noisy::noisy(const noisy& src) { cout << "HELLO! (COPIED)" << endl; // custom definition}

void func(noisy b) { noisy c;}

void main() { noisy a; func(a);}

Aahh, that’s better

Page 20: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

20

More Examples – Scope

void main() { noisy a; noisy b(a); noisy c = a; c = b;}

int x = 5;

void main() { if (x == 5) { noisy a; } else { noisy b,c,d,e; }}

Page 21: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

21

Copy-Constructors

• When variable is initialized from value of same type, it has been copy-constructed

• By default, every type has the ‘obvious’ copy-constructor:

point a(5,7); // a is CONSTRUCTED via (x,y) argumentspoint b(a); // b is COPY-CONSTRUCTED from apoint c = a; // c is COPY-CONSTRUCTED from ac = b; // c is COPIED from b

same as point c(a);

whatever a;whatever b(a); // b initialized to byte-by-byte copy of a

Page 22: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

22

• Default copy-constructor does ‘raw’ copy

• Raw copy dangerous for some types!

b

Copy-Constructors

point a(5,7);point b(a);

a

...... 00

05

00

07

00

05

00

07

0016

0017

0018

0019

001a

001b

001c

001d

001e

001f

0020

0021

struct sound { int size; double* samples; ~sound(); // delete[] samples};

sound a = ...; // set to whateversound b(a); // UH-OH!

b4

size samples

a4 0.0

0.00.00.0

Who gets to delete[] the array of samples?

Page 23: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

23

Defining a Copy-Constructor

• Add constructor with a specific argument:

• Example:

struct name { name(const name& src); // copy-constructor declaration};

name::name(const name& src) { ... // copy-constructor definition}

if you don’t know what const means, don’t worry – just remember to put it!

point::point(const point& src) { x = src.x; y = src.y;}

This copy-constructor does byte-by-byte copy, same asdefault copy-constructor!

Page 24: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

24

Why Copy-Constructor?

• Because some objects must be copied very carefully!sound::sound(const sound& src) { size = src.size; samples = new double[size]; for (int i = 0; i < size; ++i) samples[i] = src.samples[i];}

sound a = ...;sound b(a); // NO PROBLEM!

b4

size samples

a4 0.0

0.00.00.0

0.00.00.00.0

Page 25: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

25

Problem: Need Copy-Operator Too

• Besides copy-constructor, there’s another way to (accidentally) raw-copy!sound a = ...;sound b(a); // OK, use smart copy-constructorb = a; // UH-OH! copy-operator still stupid!

b4

size samples

a4 0.0

0.00.00.0

0.00.00.00.0

back in same problematic situation!

plus memory leak!

Page 26: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

26

Defining a Copy-Operator

• Copy-constructor and copy-operator are almost always defined together

• Key difference: copy-operator must assume object already initialized!

void sound::operator=(const sound& src) { delete[] samples; // delete old array // paste code from copy-constructor}

sound a = ...;sound b(a); // COPY-CONSTRUCTORa.samples[0] = 5.0;b = a; // COPY-OPERATOR

b4

size samples

a4 5.0

0.00.00.0

5.00.00.00.0

first copy of a

(deleted)

Page 27: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

27

Defining a Copy-Operator

• Add member function with special name and one specific argument:struct name { void operator=(const name& src); // declaration};

void name::operator=(const name& src) { ... // definition}

void point::operator=(const point& src) { x = src.x; y = src.y;}

This copy-operatoris same as default copy-operator!

Page 28: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

28

Careful Copying – Sound Exampleclass sound { int m_size; double* m_samples; void copy(const sound& src);public: sound(char* filename); sound(const sound& src); ~sound(); void operator=(const sound& src);};

sound gaga("pokerface.mp3"); // constructor calledsound radiohead("creep.mp3"); // constructor calledsound music(gaga); // copy-constructor calledmusic = radiohead; // copy-operator (whew!)

sound::sound(const sound& src) { copy(src);}

void sound::operator=(const sound& src) { delete[] m_samples; copy(src);}

void sound::copy(const sound& src) { m_size = src.m_size; m_samples = new double[m_size]; for (int i = 0; i < m_size; ++i) m_samples[i] = src.m_samples[i];}

music4

size samples

5.00.00.00.0

Page 29: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

29

Careful Copying – String Exampleclass string { int m_size; char* m_chars; void copy(const string& src);public: string(char* src); // (exercise) string(const string& src); ~string(); void operator=(const string& src);};

string republican("Bush"); // constructor calledstring democrat("Obama"); // constructor calledstring prez(republican); // copy-constructor calledprez = democrat; // copy-operator (whew!)

string::string(const string& src) { copy(src);}

void string::operator=(const string& src) { delete[] m_chars; copy(src);}

void string::copy(const string& src) { m_size = src.m_size; m_chars = new char[m_size+1]; for (int i = 0; i <= m_size; ++i) m_chars[i] = src.m_chars[i];}

prez4

size chars

'B''u''s''h'0zero at end of strings

called “null terminator”

Page 30: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

30

Constructors & Implicit Conversion

• How does code like this actually work?

• A constructor like string(char*) gives compiler a way to implicitly convert!

void print(string message) { ...}

void main() { char* str = "hello"; print(str); // str is not 'string', but works anyway!}

print(str); // compiler constructs 'message' from str

Page 31: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

31

Constructors & Implicit Conversion

• How does code like this actually work?

message 5

'h' 'e' 'l' 'l' 'o' 0

main

globals

str

void print(string message) { ...}

void main() { char* str = "hello"; print(str); // str is not 'string', but works anyway!}

print

call stack

'h' 'e' 'l' 'l' 'o' 0

heap

CPU

allocated and initialized by string(char*) constructor

global data, part of .exe file

Page 32: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

32

Constructors & Implicit Conversion

• And what actually goes on here?

• Compiler uses constructor to convert!– looks for conversions to do what you asked

void string::operator=(const string& src) { delete[] m_chars; copy(src);}

void main() { string prez("Bush"); prez = "Obama"; // right-side type char*, not string!}

prez = string("Obama"); // compiler secretly does this!

a temporary unnamed string object, constructed from string(char*)

Page 33: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

33

Constructors & Implicit Conversion

5

'B' 'u' 's' 'h' 0

main

globals

prez

void string::operator=(const string& src) { delete[] m_chars; copy(src);}

void main() { string prez("Bush"); prez = "Obama"; }

operator=

src

4

'O' 'b' 'a' 'm' 0'a'

this

'O' 'b' 'a' 'm' 0'a'

'B' 'u' 's' 'h' 0

unnamed

Page 34: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

34

“Shallow Copy” vs “Deep Copy”

• Copying raw bytes is ‘shallow’ (the default)

• Duplicating entire structure is ‘deep’sound a = ...;sound b = a; // should b be independent copy?

b4

size samples

a4 0.0

0.00.00.0

0.00.00.00.0

b4

size samples

a4 0.0

0.00.00.0

shallow(danger of accidental sharing)

deep(independent copies)

Page 35: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

35

Part B. Operator Overloadingpoint a,b;point c = a+b; // add two points

Page 36: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

36

What is Operator Overloading?

• operator+(int,int) is built-in

• operator+(point,point) is not

int pos = 1;int vel = 3;pos = pos + vel; // update 1D position

point pos = {1,0};point vel = {3,0};pos = pos + vel; // update 2D position (ERROR)

warning: #include <iostream> changes error message to something crazy

Page 37: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

37

What is Operator Overloading?

• We can define what point+point means point operator+(point a, point b) { // Oh, so that's how point p = { a.x+b.x, a.y+b.y }; // I should add two return p; // point variables...}

void main() { point pos = {1,0}; point vel = {3,0}; pos = pos + vel; // OK, pos = (4,0)}

result of adding two points should probably be another point!

Page 38: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

38

Why Operator Overloading?

• Useful for strings...

• Useful for mathematics...

• Useful for iterators...

• Useful for array-like data structures...

string username = "yli983";string email = username + "@uwo.ca";

vec3 r = (A*x – b); // residualsdouble error = r*r; // dot product

operator+(string,char*)

operator*(mat3x3,vec3)operator-(vec3,vec3)operator*(vec3,vec3)

for (iter i = first; i != last; ++i) ...

iter::operator++()

dynarray<double> samples;samples[0] = -1.7; dynarray::operator[](int)

(these are not complete operator declarations; just to illustrate their form)

Page 39: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

39

Two Ways to Define an Operator

• As global function:

• As member function:

• Same code, but member functions have access to private data; globals do not

point operator+(point a, point b) { point p = { a.x+b.x, a.y+b.y }; return p;}

point point::operator+(point b) { point p = { x+b.x, y+b.y }; return p;}

Page 40: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

40

Operators and Pass-By-Reference

• If arguments are copies, can be expensivestring operator+(string a, string b) { string s(a); s.append(b); return s;}

b 5operator+

'O' 'b' 'a' 'm' 'a' 0

CPU

a 6 'B' 'a' 'r' 'a' 'c' 0'k'

5 'O' 'b' 'a' 'm' 'a' 0

6 'B' 'a' 'r' 'a' 'c' 0'k'

s 11 'B' 'a' 'r' 'a' 'c' 'k' 'O' 'b' 'a' 'm' 'a' 0

copies of input strings

Page 41: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

41

Operators and Pass-By-Reference

• So, use pass-by-reference instead!string operator+(const string& a, const string& b) { string s(a); s.append(b); return s;}

boperator+

CPU

a

5 'O' 'b' 'a' 'm' 'a' 0

6 'B' 'a' 'r' 'a' 'c' 0'k'

s 11 'B' 'a' 'r' 'a' 'c' 'k' 'O' 'b' 'a' 'm' 'a' 0

Page 42: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

42

Examplestruct cyclic_int { int value; int max_value; void operator++();};

void cyclic_int::operator++() { if (++value >= max_value) // wrap back to zero value = 0;}

void main() { cyclic_int minutes = {59,60}; ++minutes; // ++ goes from 59 to 0}

Page 43: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

43

Concept Checklist

• You should understand meaning of... globals, call stack, heap variable scope pointer reference static array dynamic array struct pass-by-value pass-by-reference

class member variable member function information hiding constructors copy constructor/operator destructor shallow copy, deep copy overloaded operator

Page 44: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

44

Comment on Naming Conventions

Two major conventions:1. lower_case

2. CamelCase

struct user_defined_type { void member_function(); int m_member_variable;};user_defined_type variable_name;

Read thrilling history of CamelCase at http://en.wikipedia.org/wiki/Camelcase

struct UserDefinedType { void memberFunction(); int mMemberVariable;};UserDefinedType variableName;

Page 45: Constructors, Destructors, Operator Overloading CS 1037 Fundamentals of Computer Science II.

45

Comment on Naming Conventions

Notes are in lower_case for three reasons:1. Standard C++ libraries use it (STL) 2. I recently switched to it (after 12 years)3. The most reliable way to parse code is

by context, not names; don’t let your brain learn to rely on wrong clues

aaa bbb(ccc ddd) { // brain should be able to infer return ddd.eee(); // a lot from usage/context}