web-dev-qa-db-ja.com

クラスにはいくつのコンストラクターがありますか?

私は今後のC++試験の準備をしていますが、クラスとコンストラクターに関する次の質問に出くわしました。

クラスFractionにはいくつのコンストラクターがありますか?」

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

私はそれが1つだけだと思ったが、彼らは3つあると提案した:

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

または言い換えれば:
デフォルト値を持つ関数はオーバーロードされた関数ですか?

57

投稿された宣言に対応するコンストラクタは1つだけで、3つのオーバーロードはありません。

呼び出し

_Fraction();
Fraction(n);
_

以下と同等です:

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

宣言に対応するコンストラクタは1つしかないことを確信させるもう1つの方法は、3つではなく1つのコンストラクタを定義するだけでよいということです。

デフォルト引数に関するC++ 11標準のセクションには、次のものがあります。

8.3.6デフォルト引数

1initializer-clauseparameter-declarationthisで指定されている場合initializer-clauseがデフォルト引数として使用されます。デフォルト引数は、末尾の引数が欠落している呼び出しで使用されます。

2 [例:宣言

_void point(int = 3, int = 4);
_

int型のゼロ、1、または2つの引数で呼び出すことができる関数を宣言します。次のいずれかの方法で呼び出すことができます。

_point(1,2); point(1); point();
_

最後の2つの呼び出しは、それぞれpoint(1,4)およびpoint(3,4)と同等です。 —例の終了]

次に主な質問です。

クラスFractionにはコンストラクタがいくつありますか?

質問を組み立てた人が、コンストラクターのセットに明示的に削除しない限りコンパイラーによって暗黙的に生成される移動コンストラクターとコピーコンストラクターを含める場合、答えはです。その場合、質問はトリックの質問です。

55
R Sahu

デフォルト値を持つ関数はオーバーロードされた関数ですか?

いいえ。オーバーロードは次のようになります

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

独自の実装(定義)がありますが、デフォルトのパラメーターを持つ関数には単一の実装があります。


私はそれが1つだけだと思ったが、彼らは3つがあると示唆した...

"クラスFractionにはコンストラクタがいくつありますか?"

これは、単一のconstructor宣言に利用可能な呼び出しバリアントを見せることを欺くためのトリックの質問です。

definite与えられたコードスニペットの答えは(言葉でthree)です。

1つの特殊なコンストラクター(呼び出しの3つのバリアントを提供)があり、コンパイラーは、deleteを使用しない場合、またはカスタム実装を提供しない場合、コピーおよび移動コンストラクターを自動的に生成します。

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

そのような試験のために、あなたが答えれば

クラスには1つのコンストラクターがあります

とにかく間違っています。あなたが答えるなら

クラスには3つのコンストラクターがあります(あなたが書いたように、それは受け入れられた答えです)

あなたはその理由を深く説明する必要があります(上で説明したように)。
口頭試験では、理由を正確にバックアップするようにお願いします。そのため、見習いテストを行います。

27

質問に対する答えは、次の3つのフォローアップの質問に関連しています。

  1. C++ 11、C++ 11、またはC++ 14以降
  2. 暗黙的に定義されたコンストラクターはカウントされますか?
  3. メンバーは何ですか?コピーできないメンバーが存在すると、暗黙的なコピーコンストラクターが削除されます。

明示的な定義は1つのコンストラクターのみです。コンパイラーは、呼び出しが明示的に0、1、または2つの引数を提供するかどうかに関係なく、3つの引数の呼び出しを挿入します。

'11より前では、移動コンストラクタはありません。'11では、2つの暗黙的なコンストラクタ定義Fraction(const Fraction &) noexceptFraction(Fraction &&) noexceptがあり、アクセス可能 cppreference をチェックします'14暗黙的に定義された移動コンストラクターの変更がある場合のルール。

あなたが得た質問は、残念ながら無邪気に見えますが、かなり技術的です。あなたのクラスがC++を単純化しすぎることを主張しないことを望みます。それはそれを学ぶための最悪の方法です。

18
TheCppZoo

コンストラクターの宣言は1つだけです。
反対側:

同じスコープ内の単一の名前に対して2つ以上の異なる宣言が指定されている場合、その名前はオーバーロードされていると言われます。

そのため、ここではoverloadedという用語は使用しません。

5
skypjack