Department of Engineering

IT Services

C++ constructors

Constructors

Constructors are special member functions used when an object is "constructed" (created). They have the same name as the class. The following code creates a class called A, then an object of that type.

class A { public: int i; }; int main() { A a; }

There's no explicit function called A - when a is created, a constructor is used that the compiler has created.

This time we'll create a constructor that, given an integer, sets the member variable i to that value.

class A { public: int i; A(int x) { i=x;}; }; int main() { A a; }

Though we don't use that constructor, the code doesn't compile, because as soon as you start writing your own constructors, none of the default constructors are created. The error message will be something like

//  error: no matching function for call to A::A()
//  note: candidates are: A::A(int)
//  note:                 A::A(const A&)

(more about that final line later) In the following, a default value is defined for the constructor argument (i.e. if no value is supplied, 7 is used). Now compilation works.

class A { public: int i; A(int x=7) { i=x;}; }; int main() { A a; }

In the next example an argument is given when an object of type A is created, so that's ok too.

class A { public: int i; A(int x) { i=x;}; }; int main() { A a(1); }

The next example has an explicit constructor for when no parameter is given, and another constructor for when a single integer parameter is given. The programmer's trying to create a with one parameter, and b using no parameters.

class A { public: int i; A() {}; A(int x) { i=x;}; }; int main() { A a(1); A b(); }

The code compiles, but doesn't do what the programmer intended. Adding

b.i=0;

exposes the problem - there's a compilation error. To run the constructor with no parameters, A b; is needed. A b(); is a prototype for a function b that returns an object of type A.

Copy constructor

There's another type of constructor - it's called a copy constructor. It's used when an object is created by a copy being taken of an existing variable.

class A { public: int i; A(const A&){}; // Copy constructor }; int main() { A a; A b=a; }

But the code doesn't compile - copying works, but a itself isn't created. Again, because we're created a constructor, no default constructors are created so we get errors like the following

//defaultconstructors4.cc:12: error: no matching function for call to A::A()
//defaultconstructors4.cc:6: note: candidates are: A::A(const A&)

If we provide our own constructors both for creating and copying, all's ok.

class A { public: int i; A(){}; A(const A&){}; }; int main() { A a; A b=a; }

Member initializer list

Constructor functions are where you often initialise values. Suppose you had a class looking like this

class A { public: int i; int& reference; }

and you wanted reference to be a reference to i. You could try this, initialising in the constructor.

class A { public: int i; int& reference; A(){ reference=i; }; }; int main() { A a; }

But it won't compile, because you can't create a reference without it having a value. This is a situation where you need to use a "Member initializer list". In the example below, the body of the constructor code does nothing, but the :reference(i) part ensures that the correct constructor for reference is used, one provided by the compiler that takes an argument used to initialise the reference.

class A { public: int i; int& reference; A():reference(i){}; }; int main() { A a; }

This is also useful with inherited classes. In the following example, the derived class inherits from the base class. By default when an object of a derived type is created, the constructor of the base class is run, then the default constructor of the derived class. But here we want base(int num) to be called, not base().

class base { public: int i; base(int num){i=num;}; base(){}; }; class derived: public base { public: derived(int num):base(num) {} ; }; int main() { base b; derived d(1); }