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;
}