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

C++: Constructor, Copy Constructor and Assignment operator

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