Home » C++ » How many constructors does the class have?

How many constructors does the class have?

Posted by: admin November 30, 2017 Leave a comment

Questions:

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?

Answers:

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.

Questions:
Answers:

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.

Questions:
Answers:

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.

Questions:
Answers:

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.

Questions:
Answers:

This kind of function definition defines a single function but 2 additional calling syntaxes. The subtle difference becomes apparent when taking function pointers or matching a template function argument to overloaded functions: in that case you only have a function with full argument list as the available overloaded type.

Now the tricky thing is that we are talking about a constructor here, and a constructor does not engage in the same kind of overloading resolution as an ordinary function and is, for all purposes, not accessible other than syntactically. In particular, this definition does count separately as a default constructor. It also counts separately as a converting constructor from int and can be used as ((Fraction)3).

So for all practical purposes, it creates three different syntactic entities in the constructor category. And as opposed to ordinary functions, there is no functional context where overload resolution would expose the difference between three actual function signatures and three merely syntactical calling conventions.

This is not a good question for a written test. This is really something for an oral exam since there are so many subtleties involved that the difference between a formally correct answer (if any) and a formally wrong answer is not likely to correlate well with actual knowledge and skill, and the reasoning behind any answer is more important than the answer itself.

Questions:
Answers:

Because it depends on the arguments you pass:

Fraction() --> Fraction(0,1)
Fraction(n)---> Fraction(n,1)
Fraction(n,m)

So it gives 3 constructors. No overloading is taking place here.

Questions:
Answers:

You can create the Fraction object in three different ways using the single constructor declared int the above class. Constructor has default parameters. If you don’t pass any argument, it assumes the respective value for the argument.

  1. Fraction a;
    // numerator will be 0 and denominator will be 1

  2. Fraction a(10);
    // numerator will be 10 and denominator will be 1

  3. Fraction a(10, 20);
    // numerator will be 10 and denominator will be 20