这个类有多少个构造函数?

时间:2022-11-14 23:51:04

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

我正在准备即将到来的c++考试,遇到了关于类和构造函数的问题:

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?

或者换句话说:具有默认值的函数是重载函数吗?

7 个解决方案

#1


55  

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:

关于默认参数的c++ 11标准有以下部分:

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.

如果在参数声明中指定了initializer-子句,这个initializer-子句被用作默认参数。默认参数将用于调用拖尾参数丢失的调用。

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:

声明一个可以用0、1或2个int类型的参数调用的函数。

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

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

最后两个调用分别对应点(1,4)和点(3,4)。端例子)

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.

如果构造问题的人希望在构造函数集合中包含move构造函数和copy构造函数(除非显式地删除,否则编译器将隐式生成这些构造函数),那么答案是3。在这种情况下,问题是一个脑筋急转弯。

#2


27  

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).

给出的代码片段的确切答案是3(用词3)。

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.

你需要深入地解释为什么你这么认为(如上所述)。在任何口试中我都会问你为什么,所以我会在学徒考试中做。

#3


18  

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. 在c++ 11, c++ 11,或c++ 14等之前?
  3. Do the implicitly defined constructors count?
  4. 隐式定义的构造函数值吗?
  5. What are the members? The presence of a non-copyable member will delete the implicit copy constructor.
  6. 有哪些成员?非版权成员的存在将删除隐式复制构造函数。

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.

显式定义只是一个构造函数;编译器将插入一个三参数调用,不管调用显式地提供0、1还是2个参数。

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.

在前11年没有移动构造函数,在11年有两个隐式构造函数定义,分数(const Fraction &) noexcept和分数(Fraction &) noexcept,检查可访问的cppreference,在14年有隐式定义的移动构造函数改变的规则。

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.

不幸的是,你得到的问题看上去很无辜,但却很技术性;我希望你的课不要过分简化c++,这是学习它最糟糕的方式。

#4


6  

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.

正因为如此,我才不用重载这个词。

#5


-4  

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).

现在需要注意的是,这里我们讨论的是构造函数,构造函数不像普通函数那样进行重载解析,而且,出于所有目的,除了从语法上讲,它是不可访问的。特别是,这个定义作为默认构造函数单独计算。它还作为一个转换构造函数从int中单独计数,可以用作(分数)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.

这对笔试来说不是一个好问题。这真的是一个口试,因为涉及很多微妙的区别正式正确答案(如果有的话)和一个正式错误的答案不太可能与实际知识和技能,和任何答案背后的推理是比答案本身更重要。

#6


-5  

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.

它给出了3个构造函数。这里没有超载。

#7


-6  

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.

使用在上面类中声明的单个构造函数,可以用三种不同的方式创建这个Fraction对象。构造函数有默认参数。如果不传递任何参数,它将假定该参数的各自值。

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

    分数;//分子是0,分母是1

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

    分数(10);//分子是10,分母是1

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

    分数(10、20);//分子是10,分母是20

#1


55  

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:

关于默认参数的c++ 11标准有以下部分:

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.

如果在参数声明中指定了initializer-子句,这个initializer-子句被用作默认参数。默认参数将用于调用拖尾参数丢失的调用。

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:

声明一个可以用0、1或2个int类型的参数调用的函数。

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

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

最后两个调用分别对应点(1,4)和点(3,4)。端例子)

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.

如果构造问题的人希望在构造函数集合中包含move构造函数和copy构造函数(除非显式地删除,否则编译器将隐式生成这些构造函数),那么答案是3。在这种情况下,问题是一个脑筋急转弯。

#2


27  

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).

给出的代码片段的确切答案是3(用词3)。

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.

你需要深入地解释为什么你这么认为(如上所述)。在任何口试中我都会问你为什么,所以我会在学徒考试中做。

#3


18  

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. 在c++ 11, c++ 11,或c++ 14等之前?
  3. Do the implicitly defined constructors count?
  4. 隐式定义的构造函数值吗?
  5. What are the members? The presence of a non-copyable member will delete the implicit copy constructor.
  6. 有哪些成员?非版权成员的存在将删除隐式复制构造函数。

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.

显式定义只是一个构造函数;编译器将插入一个三参数调用,不管调用显式地提供0、1还是2个参数。

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.

在前11年没有移动构造函数,在11年有两个隐式构造函数定义,分数(const Fraction &) noexcept和分数(Fraction &) noexcept,检查可访问的cppreference,在14年有隐式定义的移动构造函数改变的规则。

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.

不幸的是,你得到的问题看上去很无辜,但却很技术性;我希望你的课不要过分简化c++,这是学习它最糟糕的方式。

#4


6  

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.

正因为如此,我才不用重载这个词。

#5


-4  

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).

现在需要注意的是,这里我们讨论的是构造函数,构造函数不像普通函数那样进行重载解析,而且,出于所有目的,除了从语法上讲,它是不可访问的。特别是,这个定义作为默认构造函数单独计算。它还作为一个转换构造函数从int中单独计数,可以用作(分数)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.

这对笔试来说不是一个好问题。这真的是一个口试,因为涉及很多微妙的区别正式正确答案(如果有的话)和一个正式错误的答案不太可能与实际知识和技能,和任何答案背后的推理是比答案本身更重要。

#6


-5  

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.

它给出了3个构造函数。这里没有超载。

#7


-6  

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.

使用在上面类中声明的单个构造函数,可以用三种不同的方式创建这个Fraction对象。构造函数有默认参数。如果不传递任何参数,它将假定该参数的各自值。

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

    分数;//分子是0,分母是1

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

    分数(10);//分子是10,分母是1

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

    分数(10、20);//分子是10,分母是20