0

Сколько конструкторов у класса?

14

Я готовлюсь к грядущему экзамену по C++ и столкнулся с вопросом о классах и конструкторах:

Сколько конструкторов имеет класс Fraction?

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

Я думал, что у него только один конструктор, но мне сказали, что их три:

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

Или по-другому:
Является ли функция с параметрами по умолчанию перегруженной функцией?

Помогите разобраться: как правильно интерпретировать количество конструкторов в данном случае?

3 ответ(ов)

0

Вопрос, который вы задали, относится к концепции перегрузки конструкторов в C++. В представленном коде:

Fraction();
Fraction(n);

можно интерпретировать как:

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

Таким образом, фактически в объявлении класса всего один конструктор. Вы можете убедиться в этом, поскольку для реализации достаточно определить лишь один конструктор, а не три.

Соглашение C++11 о значениях по умолчанию (раздел 8.3.6) гласит:

Если в объявлении параметра задан initializer-clause, это значение будет использоваться как значение по умолчанию. Значения по умолчанию будут использованы в случаях, когда отсутствуют конечные аргументы.

Чтобы проиллюстрировать это, приведен пример:

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

Этот пример показывает, что функция может быть вызвана с нулем, одним или двумя аргументами типа int. Например, вызовы:

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

будут эквивалентны point(1, 4) и point(3, 4) соответственно.

Теперь к вашему главному вопросу:

Сколько конструкторов у класса Fraction?

Если вы имеете в виду, что в состав конструкторов класса следует включить конструкторы перемещения и копирования, которые создаются компилятором автоматически, если не были явно удалены, тогда ответ — три. В этом случае вопрос становится немного хитрым.

0

Является ли функция с параметрами по умолчанию перегруженной?

Нет. Перегруженные функции выглядят следующим образом:

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

Каждая из них имеет свою реализацию (определение), в то время как функция с параметрами по умолчанию имеет единую реализацию.


Я думал, что это только одна, но они предположили, что их три: ...

"Сколько конструкторов имеет класс Fraction?"

Это трюк, предназначенный чтобы сбить вас с толку, показывая доступные варианты вызова для одного объявления конструктора.

Определенный ответ для данного кода — 3 (словами — три).

Существует один специализированный конструктор (который обслуживает три варианта вызова), а компилятор автоматически генерирует конструктор копирования и конструктор перемещения, если вы их не delete, или не предоставите собственную реализацию:

Fraction(int numerator = 0, int denominator = 1); // (1)
// Лишний, просто для демонстрации:
Fraction(const Fraction& rhs) = default; // (2)
Fraction(Fraction&& rhs) = default; // (3)

Поэтому, если на таком экзамене вы ответите

Класс имеет один конструктор

Это неверно. Если вы ответите

Класс имеет три конструктора (как вы написали, это принятый ответ)

вам потребуется подробно объяснить, почему вы так считаете (как объяснено выше).

В любом устном экзамене я бы попросил вас обосновать, почему именно, так же как я бы сделал на практическом тесте.

0

В данном случае вы правы, что у вас есть только одно объявление конструктора. Когда мы говорим о перегрузке, подразумевается, что для одного и того же имени в одном и том же пространстве имен существует два или более различных объявлений. В вашем случае, если имеется только одно объявление конструктора, это не соответствует определению перегрузки.

Поэтому я бы не использовал термин перегрузка в этом контексте.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь