C++ Tutorial
C++ Constructors
A constructor runs when an object is created. Use it to set fields so the object starts valid.
Code that runs at creation
A constructor is a special method. It has the same name as the class, and it has no return type — not evenvoid. The compiler calls it when you create an object. That is the moment to give fields real values, so you never print an uninitialized int.
You already created objects with Player p;. If you write no constructor, C++ still provides a default one that does nothing useful to your fields. Write your own when the object must start in a known state.
Default constructor
A constructor with no parameters is the default constructor. Point origin; calls it. Here it sets x and y to 0 so the point is usable at once.
Example
#include <iostream>
using namespace std;
class Point {
public:
int x;
int y;
Point() {
x = 0;
y = 0;
}
};
int main() {
Point origin;
cout << origin.x << " " << origin.y << endl;
return 0;
}Constructor with parameters
Pass values into the constructor when each object needs a different start. Point p(3, 4); calls the version that takes two ints. You do not write p.x = 3; afterward unless you want to change it later.
Example
#include <iostream>
using namespace std;
class Point {
public:
int x;
int y;
Point(int x_in, int y_in) {
x = x_in;
y = y_in;
}
};
int main() {
Point p(3, 4);
cout << p.x << " " << p.y << endl;
return 0;
}Compile this in /cpp/try. Create two points with different arguments and print both.
Initializer list
After the parameter list, a colon starts an initializer list. It sets each field before the constructor body runs. For simple int fields it matches assigning in the body. It is the usual style, and it is required later for some member types. Empty braces after the list mean the body has nothing left to do.
Example
#include <iostream>
using namespace std;
class Point {
public:
int x;
int y;
Point(int x_in, int y_in) : x(x_in), y(y_in) {}
};
int main() {
Point p(3, 4);
cout << p.x << " " << p.y << endl;
return 0;
}List members in the same order they are declared in the class. The compiler initializes in declaration order anyway; matching that order keeps the source honest.
Both constructors together
Constructors overload like functions. One version takes no arguments. Another takes two ints. The call picks the match. If you write any constructor, C++ does not keep the empty default unless you write that one too.
Example
#include <iostream>
using namespace std;
class Point {
public:
int x;
int y;
Point() : x(0), y(0) {}
Point(int x_in, int y_in) : x(x_in), y(y_in) {}
};
int main() {
Point origin;
Point p(3, 4);
cout << origin.x << " " << origin.y << endl;
cout << p.x << " " << p.y << endl;
return 0;
}After you add Point(int, int) only, the line Point origin; fails to compile. ProvidePoint() as well if you still want objects with no arguments.
Constructors do not return
Do not write return with a value in a constructor. Finish by leaving the fields set. Next: who is allowed to read and write those fields.
Worked examples
The short listings above are there so you can see the grammar. The programs here use the same statements on quantities that already have units: a speed, a pH, a count of bases. They are classroom numbers. Air resistance is ignored. g is 9.81 m/s² unless a line says otherwise.
Open them in the C++ editor at /cpp/try. Change one measurement and check whether the result still has the right unit.
Physics
A projectile that starts valid
From rest, you still need mass and an initial speed even if that speed is 0. The constructor writes both fields so you cannot forget one. 0.05 kg at 12 m/s is a dart, not a car.
KE = ½ m u²
Example
#include <iostream>
using namespace std;
class Dart {
double mass;
double u;
public:
Dart(double m, double speed) : mass(m), u(speed) {}
double ke() { return 0.5 * mass * u * u; }
};
int main() {
Dart d(0.05, 12.0);
cout << "KE = " << d.ke() << " J" << endl;
return 0;
}Chemistry
A bottle labelled at creation
Constructing a Sample with a formula and a mass is the same as writing the label before you weigh. "NaCl" and 5.0 g start together. An empty object you fill later is how labels get lost.
Example
#include <iostream>
#include <string>
using namespace std;
class Sample {
string formula;
double grams;
public:
Sample(string f, double g) : formula(f), grams(g) {}
void print() { cout << formula << " " << grams << " g" << endl; }
};
int main() {
Sample s("NaCl", 5.0);
s.print();
return 0;
}