How many constructors does the class have?

I'm preparing for an upcoming C++ exam and came across this question about classes and constructors:

How many constructors does the class Fraction have?"

class Fraction {
//...
public:
   Fraction(int numerator = 0, int denominator = 1);
//...
};

I thought it's only one, but they suggested there are three:

Fraction();
Fraction(n);
Fraction(n, d);

Or in other words:
Is a function with default values an overloaded function?


There is only one constructor corresponding to the posted declaration, not three overloads.

The calls

Fraction();
Fraction(n);

are equivalent to:

Fraction(0, 1);
Fraction(n, 1);

One more way to convince yourself that there is only one constructor corresponding to the declaration is that you only need to define one constructor, not three.

The section of the C++11 standard on default arguments has this:

8.3.6 Default arguments

1 If an initializer-clause is specified in a parameter-declaration this initializer-clause is used as a default argument. Default arguments will be used in calls where trailing arguments are missing.

2 [ Example: the declaration

void point(int = 3, int = 4);

declares a function that can be called with zero, one, or two arguments of\ type int. It can be called in any of these ways:

point(1,2); point(1); point();

The last two calls are equivalent to point(1,4) and point(3,4), respectively. —end example ]

Now the main question.

How many constructors does the class Fraction have?

If the person that framed the question wants to include the move constructor and the copy constructor, which are implicitly generated by the compiler unless explicitly deleted, in the set of constructors, then the answer is three. In that case, the question is a trick question.


Is a function with default values an overloaded function?

No. Overloads look like

Fraction();
Fraction(int numerator);
Fraction(int numerator, int denominator);

and have each their own implementation (definition), while a function with default parameters has a single implementation.


I thought it's only one, but they suggested there are 3: ...

"How many constructors does the class Fraction have?"

It's a trick question, designed to fool you showing the available call variants for a single constructor declaration.

The definite answer for the given code snippet is 3 (in words three).

There's one specialized constructor (which serves three variants of calling), and the compiler generates a copy and move constructor automatically if you don't delete them, or provide a custom implementation:

Fraction(int numerator = 0, int denominator = 1); // (1)
// Redundant, just for demonstration:
Fraction(const Fraction& rhs) = default; // (2)
Fraction(Fraction&& rhs) = default; // (3)

So for such exam, if you will answer

The class has one constructor

That's wrong anyways. If you will answer

The class has three constructors (as you wrote that is the accepted answer)

you'll need to explain in depth, why you think so (as explained above).
In any oral exam I'd ask you to backup why exactly, so I'd do in an apprentice test.


The answer to your question is relative to these three follow-up questions:

  1. Before C++ 11, C++ 11, or C++14 and beyond?
  2. Do the implicitly defined constructors count?
  3. What are the members? The presence of a non-copyable member will delete the implicit copy constructor.

The explicit definition is only one constructor; the compiler will insert a three-argument call regardless of whether the call explicitly supplies 0, 1, or 2 arguments.

In pre-'11 there are no move constructors, in '11 there are two implicit constructor definitions, Fraction(const Fraction &) noexcept and Fraction(Fraction &&) noexcept, check the accessible cppreference, in '14 the rules of when there is an implicitly defined move constructor change.

The question you got is unfortunately innocently looking but quite technical; I hope your class does not insist on oversimplifying C++, it is the worst way to learn it.


You have only one declaration of a constructor.
On the other side:

When two or more different declarations are specified for a single name in the same scope, that name is said to be overloaded

Because of that, I'd not use the term overloaded here.