Digital Garden
Computer Science
C++
Classes

Classes

Constructors

In C++ primitive types don't have constructors so you need to initialize them in the constructor.

#include <iostream>
using namespace std;
 
class Point {
private:
    double m_x;
    double m_y;
 
public:
    // default constuctor
    Point() = default; // or just Point(){};
    Point(double x, double y) { // Point object is already initialized
        m_x = x; // lots of copiessssss
        m_y = y;
    }
};
 
int main()
{
    Point p1(); // default constructor, very bad nothing is initialized
    Point p2(1, 2);
}

However the above example is a bad way of creating a constructor as the object is already initialized and then the values are changed, this leads to lots of member-wise copying unnecessarily used memory. Even worse is the default constructor which leaves the attributes uninitialized because as mentioned the primitives don't have a default constructor.

Initializer lists

Instead in modern C++ we use initializer lists which stops the copying and everything bad mentioned above.

#include <iostream>
using namespace std;
 
class Point {
private:
    double m_x;
    double m_y;
 
public:
    // default constuctor
    Point() : m_x(0), m_y(0) {};
    Point(double x, double y): m_x(x), m_y(y) {};
};
 
int main()
{
    Point p1(); // default constructor x and y are 0
    Point p2(1, 2);
}

Default parameters

We can improve the above constructor even more by using default parameter values. Because the arguments also don't change and we don't want them to we can add const.

#include <iostream>
using namespace std;
 
class Point {
private:
    double m_x;
    double m_y;
 
public:
    Point(const double x = 0, const double y = 0): m_x(x), m_y(y) {};
};
 
int main()
{
    Point p1(); // x and y are 0
    Point p2(1, 2);
}

Explicit constructors

You need to be very careful with creating constructors and often have to define a constructor as explicit otherwise something might just implicitly create an object of a certain type.

#include <iostream>
using namespace std;
 
class Complex {
private:
    double real;
    double imag;
 
public:
    // Default constructor
    explicit Complex(double r = 0.0, double i = 0.0)
        : real(r), imag(i)
    {}
 
    // compare two Complex numbers
    bool operator==(Complex rhs) { return (real == rhs.real && imag == rhs.imag); }
};
 
int main()
{
    Complex com1(3.0, 0.0);
    cout << com1 == 3.0 << endl; // if not explicit this will create a Complex object (3.0,0.0) and compare them
    return 0;
}

Anonymous/temporary objects

These objects have no name and are thrown away after use.

#include <iostream>
using namespace std;
class Point {
    double m_x, m_y;
public:
    Point(double x = 0, double y = 0)
        : m_x(x), m_y(y)
    {}
 
    void print() {
        cout << "(" << m_x << "/" << m_y << ")" << endl;
    }
};
 
int main()
{
    Point(1, 3).print();
    return 0;
}

Constant member functions

Constant member functions are denoted by writting const at the end of the definition. If in this class function changes a member variable of the class it will generate a compiler error, however, reading of a class variables is okay inside of the function.

#include<iostream>
using namespace std;
class Demo {
    int val;
public:
    Demo(int x = 0): val(x) {    }
    int getValue() const {
        // val++; would not work
        return val;
    }
};
int main() {
    Demo d(8);
    cout << "The value using object d : " << d.getValue();
    return 0;
}