Post on 18-Jan-2015
description
C++ Constructors
Jussi PohjolainenTAMK 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"
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 "point.h"
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"
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 "point.h"#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 "point.h"
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 "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() << ", " << a.GetY() << endl;
cout << b.GetX() << ", " << 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 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);
};
Default Copy Constructor#include "point.h”
Point::Point(const Point& p)
{
x_ = p.x_;
y_ = p.y_;
}
...
Default Copy Constructor#include <iostream>
using namespace std;
#include "point.h"
int main() {
Point a(5,5); // Constructor
Point b = a; // Copy Constructor
b = a; // Assignment!
b.SetX(10);
cout << a.GetX() << ", " << a.GetY() << endl;
cout << b.GetX() << ", " << 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 CloneLine::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 "point.h"
int main() {
Point a(5,5); // Constructor
Point b = a; // Copy Constructor
b = a; // Assignment!
b.SetX(10);
cout << a.GetX() << ", " << a.GetY() << endl;
cout << b.GetX() << ", " << 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 Operatorint 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?
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 copyPerson& 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 Wayint 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;}