Ways to construct objects

Consider we have a Point class to represent a two-dimensional coordinates (x, y) in Cartesian coordinate system.

Default Constructor

#include <iostream>

using std::cout;
using std::endl;
using std::ostream; // for << operator overloading

class Point
{
public:
  // Overwrite the output stream
  friend ostream& operator<<(ostream& out, const Point& p)
  {
    out << "(" << p.x << ", " << p.y << ")";
    return out;
  }
private:
  double x;
  double y;
};

int main() {
  Point p1;
  cout << p1 << endl;
  return 0;
}

What is the output of the above code? What's the initial value of x and y? The answer is (0, 0). The reason why is that we actually have a default constructor as below:

Point() { // Default constructor
  x = 0;
  y = 0;
}

That is, our code is same as:

#include <iostream>

using std::cout;
using std::endl;
using std::ostream; // for << operator overloading

class Point
{
public:
  Point() { // Default constructor
    x = 0;
    y = 0;
  }

  // Overwrite the output stream
  friend ostream& operator<<(ostream& out, const Point& p)
  {
    out << "(" << p.x << ", " << p.y << ")";
    return out;
  }
private:
  double x;
  double y;
};

int main() {
  Point p1;
  cout << p1 << endl;
  return 0;
}

Use this to avoid ambiguous variables

Formally, the default constructor should be defined specifically:

#include <iostream>

using std::cout;
using std::endl;
using std::ostream; // for << operator overloading

class Point
{
public:
  Point(double x = 0.0, double y = 0.0) {
    this->x = x; // this->x is our inside member, and x is the passed parameter.
    this->y = y;
  }

  // Overwrite the output stream
  friend ostream& operator<<(ostream& out, const Point& p)
  {
    out << "(" << p.x << ", " << p.y << ")";
    return out;
  }
private:
  double x;
  double y;
};

int main() {
  Point p1;
  cout << p1 << endl;
  Point p2(2.4, 6.7);
  cout << p2 << endl;
  return 0;
}

Then we can use arbitrary (x, y) to initialize the Point. The output of above code is:

(0, 0)
(2.4, 6.7)

The this in constructor is used to disambiguate. The members x, y and parameters x, yshould be clearly differentiated.

Use Prefix to avoid ambiguous variables

Another way to differentiate the member variables and parameters is to use Prefix:

#include <iostream>

using std::cout;
using std::endl;
using std::ostream; // for << operator overloading

class Point
{
public:
  Point(double aX = 0.0, double aY = 0.0) {
    mX = aX;
    mY = aY;
  }

  // Overwrite the output stream
  friend ostream& operator<<(ostream& out, const Point& p)
  {
    out << "(" << p.mX << ", " << p.mY << ")";
    return out;
  }
private:
  double mX;
  double mY;
};

int main() {
  Point p1;
  cout << p1 << endl;
  Point p2(2.4, 6.7);
  cout << p2 << endl;
  return 0;
}

The m and a here are represented as member and argument.

Initializer Lists

The best way to initialize the member variables is to use initializer lists. We will explain why in next lesson. Now we only show how to use it.

#include <iostream>

using std::cout;
using std::endl;
using std::ostream; // for << operator overloading

class Point
{
public:
  Point(double aX = 0.0, double aY = 0.0)
    : mX(aX)
    , mY(aY) // Initialize mX and mY by initializer lists
  {
  }

  // Overwrite the output stream
  friend ostream& operator<<(ostream& out, const Point& p)
  {
    out << "(" << p.mX << ", " << p.mY << ")";
    return out;
  }
private:
  double mX;
  double mY;
};

int main() {
  Point p1;
  cout << p1 << endl;
  Point p2(2.4, 6.7);
  cout << p2 << endl;
  return 0;
}

results matching ""

    No results matching ""