C++: Constructor, Copy Constructor and Assignment operator

9,902 views

Published on

Published in: Education, Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
9,902
On SlideShare
0
From Embeds
0
Number of Embeds
112
Actions
Shares
0
Downloads
361
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

C++: Constructor, Copy Constructor and Assignment operator

  1. 1. C++ Constructors Jussi Pohjolainen TAMK University of Applied Sciences
  2. 2. Constructors <ul><li>Constructor is a “init function” that is called when an object is created </li></ul><ul><li>C++ provides default constructor (= constructor with no parameters) </li></ul><ul><li>Constructor has the same name than the class </li></ul><ul><li>Constructor does not return anything </li></ul><ul><li>Constructor usually initalizes class members </li></ul>
  3. 3. point.h <ul><li>#ifndef _POINT_H_ </li></ul><ul><li>#define _POINT_H_ </li></ul><ul><li>class Point </li></ul><ul><li>{ </li></ul><ul><li>private: </li></ul><ul><li>int x_; </li></ul><ul><li>int y_; </li></ul><ul><li>public: </li></ul><ul><li>Point(int x, int y); </li></ul><ul><li>int GetX(); </li></ul><ul><li>int GetY(); </li></ul><ul><li>}; </li></ul><ul><li>#endif </li></ul>
  4. 4. point.cpp <ul><li>#include &quot;point.h&quot; </li></ul><ul><li>Point::Point(int x, int y) </li></ul><ul><li>{ </li></ul><ul><li>x_ = x; </li></ul><ul><li>y_ = y; </li></ul><ul><li>} </li></ul><ul><li>int Point::GetX() </li></ul><ul><li>{ </li></ul><ul><li>return x_; </li></ul><ul><li>} </li></ul><ul><li>int Point::GetY() </li></ul><ul><li>{ </li></ul><ul><li>return y_; </li></ul><ul><li>} </li></ul>
  5. 5. main.cpp <ul><li>#include <iostream> </li></ul><ul><li>#include ”point.h&quot; </li></ul><ul><li>using namespace std; </li></ul><ul><li>int main() </li></ul><ul><li>{ </li></ul><ul><li>Point p = Point(5,5); </li></ul><ul><li>cout << p.GetX() << endl; </li></ul><ul><li>return 0; </li></ul><ul><li>} </li></ul>
  6. 6. Default Constructor <ul><li>Default constructor is a constructor that can be called without parameters: </li></ul><ul><ul><li>class Example { </li></ul></ul><ul><ul><li>public: </li></ul></ul><ul><ul><ul><li>Example(int x=0, int y=0); </li></ul></ul></ul><ul><ul><li>} </li></ul></ul>
  7. 7. Initialization Lists <ul><li>Basic rule: initialize all class members in constructor </li></ul><ul><li>Use initialization lists for initialization </li></ul><ul><li>Initialization list is more efficient than assignment </li></ul>
  8. 8. Example of Initialization List <ul><li>#ifndef _POINT_H_ </li></ul><ul><li>#define _POINT_H_ </li></ul><ul><li>class Point { </li></ul><ul><li>private: </li></ul><ul><li>int x_; </li></ul><ul><li>int y_; </li></ul><ul><li>public: </li></ul><ul><li>Point(int x, int y); </li></ul><ul><li>}; </li></ul><ul><li>#endif </li></ul>
  9. 9. Example of Initialization List <ul><li>#include &quot;point.h&quot; </li></ul><ul><li>Point::Point(int x, int y) : x_(x), </li></ul><ul><li>y_(y) </li></ul><ul><li>{ </li></ul><ul><li>} </li></ul>
  10. 10. this - pointer <ul><li>this pointer is used as a pointer to the class object instance by the member function </li></ul><ul><li>This pointer stores the address of the class instance </li></ul>
  11. 11. Example about this <ul><li>#include <iostream> </li></ul><ul><li>#include ”point.h&quot; </li></ul><ul><li>using namespace std; </li></ul><ul><li>int main() </li></ul><ul><li>{ </li></ul><ul><li>Point p = Point(5,5); </li></ul><ul><li>cout << &p << endl; // prints 0xbffffa98 </li></ul><ul><li>return 0; </li></ul><ul><li>} </li></ul>
  12. 12. Example about this <ul><li>#ifndef _POINT_H_ </li></ul><ul><li>#define _POINT_H_ </li></ul><ul><li>class Point { </li></ul><ul><li>private: </li></ul><ul><li>int x_; </li></ul><ul><li>int y_; </li></ul><ul><li>public: </li></ul><ul><li>Point(int x, int y); </li></ul><ul><li>void PrintAddress(); </li></ul><ul><li>}; </li></ul><ul><li>#endif </li></ul>
  13. 13. Example about this <ul><li>#include &quot;point.h&quot; </li></ul><ul><li>#include <iostream> </li></ul><ul><li>using namespace std; </li></ul><ul><li>Point::Point(int x, int y) : x_(x), </li></ul><ul><li>y_(y) { } </li></ul><ul><li>void Point::PrintAddress() </li></ul><ul><li>{ </li></ul><ul><li>cout << this ; </li></ul><ul><li>} </li></ul>
  14. 14. Example about this <ul><li>#include <iostream> </li></ul><ul><li>using namespace std; </li></ul><ul><li>#include &quot;point.h&quot; </li></ul><ul><li>int main() { </li></ul><ul><li>Point a(5,5); </li></ul><ul><li>cout << &a << endl; // 0xbffffa98 </li></ul><ul><li>a.PrintAddress(); // 0xbffffa98 </li></ul><ul><li>return 0; </li></ul><ul><li>} </li></ul>
  15. 15. Usage? <ul><li>#ifndef _POINT_H_ </li></ul><ul><li>#define _POINT_H_ </li></ul><ul><li>class Point { </li></ul><ul><li>private: </li></ul><ul><li>int x ; </li></ul><ul><li>int y ; </li></ul><ul><li>public: </li></ul><ul><li> void SetX(int x); </li></ul><ul><li>void SetY(int y); </li></ul><ul><li>}; </li></ul><ul><li>#endif </li></ul>
  16. 16. Usage? <ul><li>#include &quot;point.h” </li></ul><ul><li>void Point::SetX(int x) </li></ul><ul><li>{ </li></ul><ul><li>this->x = x ; </li></ul><ul><li>} </li></ul><ul><li>void Point::SetY(int y) </li></ul><ul><li>{ </li></ul><ul><li>this->y = y ; </li></ul><ul><li>} </li></ul>
  17. 17. Destructors <ul><li>Destructor is a function that is called when the object is released from memory </li></ul><ul><li>You cannot overload destructors </li></ul><ul><ul><li>Class::~Class() { … } </li></ul></ul>
  18. 18. COPY CONSTRUCTOR
  19. 19. Introduction <ul><li>What happens here? </li></ul><ul><li>int main() { </li></ul><ul><li>Point a(5,5); </li></ul><ul><li>Point b = a; </li></ul><ul><li>b.SetX(10); </li></ul><ul><li>cout << a.GetX() << &quot;, &quot; << a.GetY() << endl; </li></ul><ul><li>cout << b.GetX() << &quot;, &quot; << b.GetY() << endl; </li></ul><ul><li>return 0; </li></ul><ul><li>} </li></ul>
  20. 20. Copy Constructor <ul><li>A copy constructor is called whenever a new variable is created from an object </li></ul><ul><ul><li>Point p(5,5); </li></ul></ul><ul><ul><li>Point a = p; // Copy constructor call! </li></ul></ul><ul><ul><li>Point b(p); // Copy constructor call! </li></ul></ul><ul><li>C++ creates default copy constructor automatically </li></ul>
  21. 21. Default Copy Constructor <ul><li>class Point { </li></ul><ul><li>private: </li></ul><ul><li>int x_; </li></ul><ul><li>int y_; </li></ul><ul><li>public: </li></ul><ul><li>Point(int x, int y); </li></ul><ul><li>Point(const Point& p); </li></ul><ul><li>int GetX(); </li></ul><ul><li>int GetY(); </li></ul><ul><li>void SetX(int x); </li></ul><ul><li>void SetY(int y); </li></ul><ul><li>}; </li></ul>
  22. 22. Default Copy Constructor <ul><li>#include &quot;point.h” </li></ul><ul><li>Point::Point(const Point& p) </li></ul><ul><li>{ </li></ul><ul><li>x_ = p.x_; </li></ul><ul><li>y_ = p.y_; </li></ul><ul><li>} </li></ul><ul><li>... </li></ul>
  23. 23. Default Copy Constructor <ul><li>#include <iostream> </li></ul><ul><li>using namespace std; </li></ul><ul><li>#include &quot;point.h&quot; </li></ul><ul><li>int main() { </li></ul><ul><li>Point a(5,5); // Constructor </li></ul><ul><li>Point b = a; // Copy Constructor </li></ul><ul><li>b = a; // Assignment! </li></ul><ul><li>b.SetX(10); </li></ul><ul><li>cout << a.GetX() << &quot;, &quot; << a.GetY() << endl; </li></ul><ul><li>cout << b.GetX() << &quot;, &quot; << b.GetY() << endl; </li></ul><ul><li>return 0; </li></ul><ul><li>} </li></ul>
  24. 24. Shallow Cloning Problem? <ul><li>class Line { </li></ul><ul><li>private: </li></ul><ul><li>Point* begin_; </li></ul><ul><li>Point* end_; </li></ul><ul><li>public: </li></ul><ul><li>Line(int x1, int y1, int x2, int y2); </li></ul><ul><li>Line(const Line& l); </li></ul><ul><li>~Line(); </li></ul><ul><li>}; </li></ul>
  25. 25. Shallow Cloning Problem? <ul><li>Line::Line(int x1, int y1, int x2, int y2) : begin(new Point(x1,y1)), </li></ul><ul><li>end(new Point(x2,y2)) </li></ul><ul><li>{ </li></ul><ul><li>} </li></ul><ul><li>Line::Line(const &Line l) </li></ul><ul><li>{ </li></ul><ul><li>begin = l.begin; </li></ul><ul><li>end = l.end; </li></ul><ul><li>} </li></ul><ul><li>Line::~Line() </li></ul><ul><li>{ </li></ul><ul><li>delete begin; </li></ul><ul><li>delete end; </li></ul><ul><li>} </li></ul>
  26. 26. Shallow Cloning Problem? <ul><li>int main() </li></ul><ul><li>{ </li></ul><ul><li>Line a(1,1,10,10); </li></ul><ul><li>Line b = a; </li></ul><ul><li>} </li></ul>
  27. 27. Implement your own Deep Clone <ul><li>Line::Line(const &Line l) </li></ul><ul><li>{ </li></ul><ul><li>int x1 = ( l.begin )->GetX(); </li></ul><ul><li>int y1 = ( l.end )->GetY(); </li></ul><ul><li>int x2 = ( l.begin )->GetX(); </li></ul><ul><li>int y2 = ( l.end )->GetY(); </li></ul><ul><li>begin = new Point(x1, y1); </li></ul><ul><li>end = new Point(x2, y2); </li></ul><ul><li>} </li></ul>
  28. 28. Rules about Copy Constructors <ul><li>If shallow cloning is enough, do not implement copy constructor </li></ul><ul><li>If you need deep copy, implement copy constructor </li></ul><ul><ul><li>Implement also destructor and assignment operator </li></ul></ul>
  29. 29. ASSIGNMENT OPERATOR
  30. 30. Assignment? <ul><li>#include <iostream> </li></ul><ul><li>using namespace std; </li></ul><ul><li>#include &quot;point.h&quot; </li></ul><ul><li>int main() { </li></ul><ul><li>Point a(5,5); // Constructor </li></ul><ul><li>Point b = a; // Copy Constructor </li></ul><ul><li>b = a; // Assignment! </li></ul><ul><li>b.SetX(10); </li></ul><ul><li>cout << a.GetX() << &quot;, &quot; << a.GetY() << endl; </li></ul><ul><li>cout << b.GetX() << &quot;, &quot; << b.GetY() << endl; </li></ul><ul><li>return 0; </li></ul><ul><li>} </li></ul>
  31. 31. Assignment Operator <ul><li>#ifndef POINT </li></ul><ul><li>#define POINT </li></ul><ul><li>class Point { </li></ul><ul><li>private: </li></ul><ul><li>int x_; </li></ul><ul><li>int y_; </li></ul><ul><li>public: </li></ul><ul><li>Point(int x, int y); </li></ul><ul><li>Point(const Point& p); </li></ul><ul><li>Point& operator=(const Point& p); </li></ul><ul><li>~Point(); </li></ul><ul><li>... </li></ul><ul><li>}; </li></ul><ul><li>#endif </li></ul>
  32. 32. Assignment Operator <ul><li>Point& Point::operator=(const Point& p) </li></ul><ul><li>{ </li></ul><ul><li>x_ = p.x_; </li></ul><ul><li>y_ = p.y_; </li></ul><ul><li>return *this; </li></ul><ul><li>} </li></ul>
  33. 33. Assignment Operator <ul><li>int main() </li></ul><ul><li>{ </li></ul><ul><li>Point a(5,5); </li></ul><ul><li>Point b(6,6); </li></ul><ul><li>Point c(7,7); </li></ul><ul><li>a = b; </li></ul><ul><li>// <=> </li></ul><ul><li>a.operator=(b); </li></ul><ul><li>a = b = c; </li></ul><ul><li>// <=> </li></ul><ul><li>(a.operator=(b)).operator=(c); </li></ul><ul><li>return 0; </li></ul><ul><li>} </li></ul>
  34. 34. <ul><li>class Heart { </li></ul><ul><li>public: </li></ul><ul><li>int bloodAmount; </li></ul><ul><li>}; </li></ul><ul><li>class Person { </li></ul><ul><li>public: </li></ul><ul><li>Heart* heart; </li></ul><ul><li>Person(); </li></ul><ul><li>~Person(); </li></ul><ul><li>}; </li></ul><ul><li>Person::Person() { </li></ul><ul><li>heart = new Heart(); </li></ul><ul><li>} </li></ul><ul><li>Person::~Person() { </li></ul><ul><li>delete heart; </li></ul><ul><li>} </li></ul><ul><li>int main() { </li></ul><ul><li>Person a; </li></ul><ul><li>Person b; </li></ul><ul><li>a = b; </li></ul><ul><li>} </li></ul>Result: a.out(8992) malloc: *** error for object 0x100160: double free *** set a breakpoint in malloc_error_break to debug WHY?
  35. 35. Why? <ul><li>A default assignment operator is used </li></ul><ul><li>Default assignment operator makes shallow copy </li></ul><ul><li>Result is two persons with one heart… </li></ul>
  36. 36. Deep copy <ul><li>Person& Person::operator=(Person& p) { </li></ul><ul><li>delete heart; </li></ul><ul><li>heart = new Heart(); </li></ul><ul><li>heart->bloodAmount = p.heart->bloodAmount; </li></ul><ul><li>return *this; </li></ul><ul><li>} </li></ul>
  37. 37. What about now… <ul><li>int main() { </li></ul><ul><li>Person a; </li></ul><ul><li>a = a; </li></ul><ul><li>} </li></ul><ul><li>Person& Person::operator=(Person& p) { </li></ul><ul><li>delete heart; </li></ul><ul><li>heart = new Heart(); </li></ul><ul><li>heart->bloodAmount = p.heart->bloodAmount; </li></ul><ul><li>return *this; </li></ul><ul><li>} </li></ul>
  38. 38. Correct Way <ul><li>int main() { </li></ul><ul><li>Person a; </li></ul><ul><li>a = a; </li></ul><ul><li>} </li></ul><ul><li>Person& Person::operator=(Person& p) { </li></ul><ul><li>if(this == &p) </li></ul><ul><li>return *this; </li></ul><ul><li>delete heart; </li></ul><ul><li>heart = new Heart(); </li></ul><ul><li>heart->bloodAmount = p.heart->bloodAmount; </li></ul><ul><li>return *this; </li></ul><ul><li>} </li></ul>

×