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
[Link]
#include "point.h"
Point::Point(int x, int y)
{
x_ = x;
y_ = y;
}
int Point::GetX()
{
return x_;
}
int Point::GetY()
{
return y_;
}
[Link]
#include <iostream>
#include ”point.h"
using namespace std;
int main()
{
Point p = Point(5,5);
cout << [Link]() << 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
[Link](); // 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;
[Link](10);
cout << [Link]() << ", " << [Link]() << endl;
cout << [Link]() << ", " << [Link]() << 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 "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!
[Link](10);
cout << [Link]() << ", " << [Link]() << endl;
cout << [Link]() << ", " << [Link]() << 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 = [Link];
end = [Link];
}
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 = ( [Link] )->GetX();
int y1 = ( [Link] )->GetY();
int x2 = ( [Link] )->GetX();
int y2 = ( [Link] )->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!
[Link](10);
cout << [Link]() << ", " << [Link]() << endl;
cout << [Link]() << ", " << [Link]() << 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;
// <=>
[Link]=(b);
a = b = c;
// <=>
([Link]=(b)).operator=(c);
return 0;
}
class Heart { Person::~Person() {
public: delete heart;
int bloodAmount; }
};
int main() {
class Person {
public:
Person a;
Heart* heart; Person b;
Person(); a = b;
~Person(); }
};
Result:
Person::Person() { [Link](8992) malloc: *** error for object
heart = new Heart(); 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 = [Link]->bloodAmount;
return *this;
}
What about now…
int main() {
Person a;
a = a;
}
Person& Person::operator=(Person& p) {
delete heart;
heart = new Heart();
heart->bloodAmount = [Link]->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 = [Link]->bloodAmount;
return *this;
}