C++ 在构造函数中,候选人需要 1 个参数,0 提供
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26076997/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
In constructor, candidate expects 1 argument, 0 provided
提问by texasflood
This is the code:
这是代码:
class cat
{
private:
int height;
public:
cat (int inputHeight);
};
cat::cat (int inputHeight)
{
height = inputHeight;
}
class twoCats
{
private:
cat firstCat;
cat secondCat;
public:
twoCats (cat theFirstCat);
void addSecondCat (cat theSecondCat);
};
twoCats::twoCats (cat theFirstCat)
{
firstCat = theFirstCat;
}
void twoCats::addSecondCat (cat theSecondCat)
{
secondCat = theSecondCat;
}
int main() {return 0;}
And these are the errors:
这些是错误:
main.cpp: In constructor ‘twoCats::twoCats(cat)':
main.cpp:24:34: error: no matching function for call to ‘cat::cat()'
main.cpp:24:34: note: candidates are:
main.cpp:9:1: note: cat::cat(int)
main.cpp:9:1: note: candidate expects 1 argument, 0 provided
main.cpp:1:7: note: cat::cat(const cat&)
main.cpp:1:7: note: candidate expects 1 argument, 0 provided
main.cpp:24:34: error: no matching function for call to ‘cat::cat()'
main.cpp:24:34: note: candidates are:
main.cpp:9:1: note: cat::cat(int)
main.cpp:9:1: note: candidate expects 1 argument, 0 provided
main.cpp:1:7: note: cat::cat(const cat&)
main.cpp:1:7: note: candidate expects 1 argument, 0 provided
I don't understand the following:
我不明白以下内容:
- Why does the constructor for
twoCats
try to call the default constructor forcat
? Surely it does not need to construct an instance ofcat
as whentwoCats
is initialised it will be passed an already initialised instance ofcat
which will have been passed theint height
argument? - Why is the same block of error messages shown twice? I called
g++ main.cpp
on Ubuntu 12.04.
- 为什么 for 的构造函数会
twoCats
尝试调用 for 的默认构造函数cat
?当然,它不需要构造一个实例,cat
因为twoCats
它何时被初始化,它将被传递一个已经初始化的实例,cat
该实例将被传递int height
参数? - 为什么同一块错误消息会显示两次?我调用
g++ main.cpp
了 Ubuntu 12.04。
采纳答案by 4pie0
You need a default constructor or initialize cat objects in twoCats
constructor initilization list explicitly to avoid default construction.
您需要一个默认构造函数或在twoCats
构造函数初始化列表中显式初始化 cat 对象以避免默认构造。
Why does the constructor for twoCats try to call the default constructor for cat? Surely it does not need to construct an instance of cat as when twoCats is initialised it will be passed an already initialised instance of cat which will have been passed the int height argument?
为什么 twoCats 的构造函数试图调用 cat 的默认构造函数?当然,它不需要构造 cat 的实例,因为在初始化 twoCats 时,它将传递一个已经初始化的 cat 实例,该实例将传递 int height 参数?
It needs to construct default values for cat
objects
它需要为cat
对象构造默认值
private:
cat firstCat;
cat secondCat;
in class twoCats
because you didn't initialize them. In your constructor
在课堂上,twoCats
因为你没有初始化它们。在你的构造函数中
cat::cat (int inputHeight)
{
height = inputHeight;
^^^^^^^^^^^^^^^^^^^^
} // this is assignment
this is assignment to already created objects.
这是对已创建对象的分配。
The rule is as follows: if you don't initialize instances explicitly in ctor
initialization list then
规则如下:如果你没有在ctor
初始化列表中显式地初始化实例,那么
- Default
ctor
is called - You eventually assign to already default constructed objects in
ctor
body.
- 默认
ctor
被调用 - 您最终分配给
ctor
body 中已经默认构造的对象。
Thus you face penalty of having additional calls if you don't initialize in initialization list.
因此,如果您不在初始化列表中初始化,您将面临额外调用的惩罚。
C++ Standard n3337 §12.6.2/10 Initializing bases and members
C++ 标准 n3337 §12.6.2/10 初始化基类和成员
In a non-delegating constructor, initialization proceeds in the following order:
— First, and only for the constructor of the most derived class (1.8), virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.
— Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
— Then, non-static data members are initializedin the order they were declared in the class definition (again regardless of the order of the mem-initializers).
— Finally, the compound-statement of the constructor body is executed.
[ Note: The declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization. — end note ]
在非委托构造函数中,初始化按以下顺序进行:
— 首先,仅对于最派生类 (1.8) 的构造函数,虚拟基类按照它们在基类的有向无环图的深度优先从左到右遍历中出现的顺序进行初始化,其中“左-to-right”是派生类基类说明符列表中基类的出现顺序。
— 然后,直接基类按照它们出现在基说明符列表中的声明顺序进行初始化(不管内存初始化器的顺序如何)。
—然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化(同样与 mem 初始化程序的顺序无关)。
—最后,执行构造函数体的复合语句。
[注意:声明顺序是为了确保基类和成员子对象以与初始化相反的顺序销毁。— 尾注 ]
回答by blackbird
I would initialize the class twoCats
like this:
我会twoCats
像这样初始化这个类:
class twoCats
{
private:
cat firstCat;
cat secondCat;
public:
twoCats (const cat& theFirstCat, const cat& theSecondCat)
: firstCat (theFirstCat), secondCat (theSecondCat)
{
}
};
The important part here is the colon after the constructor :
. It starts the member initialization list, which is the place where, if possible, all your class data members should be initialized.
这里的重要部分是构造函数后面的冒号:
。它启动成员初始化列表,如果可能,应该在此初始化所有类数据成员。
Initialization of data members is quite a complex issue in C++, I suggest you google it.
数据成员的初始化在C++中是一个相当复杂的问题,建议你google一下。
In particular, since you have two members of class type, the compiler, no matter what, tries to initialize them in your constructor. It does so for every cat, which probably is the reason you get the error message block twice. In its default, the compiler tries to initialize your cat data members using a default constructor, i.e. one without arguments. Unfortunately, cat
does not have a default constructor, since you declared one with one argument. In other words, each cat has to be initialized with one argument (or copied, or moved in C++11).
特别是,由于您有两个类类型成员,编译器无论如何都会尝试在您的构造函数中初始化它们。它对每只猫都这样做,这可能是您两次收到错误消息块的原因。默认情况下,编译器尝试使用默认构造函数(即不带参数的构造函数)初始化 cat 数据成员。不幸的是,cat
它没有默认构造函数,因为您声明了一个带有一个参数的构造函数。换句话说,每只猫都必须用一个参数初始化(或在 C++11 中复制或移动)。
I do not recommend declaring an additional constructor to cat
without arguments: It seems that there is no "default hight" of a cat, and the -1
suggested by another answer is very strange: It doesn't seem to construct a valid object, and you'd have to check for this default value before using any of cat
's member functions.
我不建议在cat
没有参数的情况下声明一个额外的构造函数:似乎没有猫的“默认高度”,-1
另一个答案的建议很奇怪:它似乎没有构造一个有效的对象,而你'在使用 的任何cat
成员函数之前,d 必须检查此默认值。
EDIT: This is from a format point of view. As for the semantics of your program, it might be wrong to copy the cats. Maybe you do need a reference (or a pointer) to the objects you initialized your twoCats with, maybe not.
编辑:这是从格式的角度来看的。至于你的程序的语义,复制猫可能是错误的。也许您确实需要一个指向您初始化 twoCats 的对象的引用(或指针),也许不需要。
回答by Cheers and hth. - Alf
Both cat instances have to be initialized, at the point when they start existing.
两个 cat 实例都必须在它们开始存在时进行初始化。
To avoid this you can defer each instance creation to when you need it.
为了避免这种情况,您可以将每个实例的创建推迟到您需要的时候。
A simple and safe way to do that is to use a std::vector
to hold the instances.
一种简单而安全的方法是使用 astd::vector
来保存实例。
class cat
{
private:
int height;
public:
cat (int inputHeight);
};
cat::cat (int inputHeight)
{
height = inputHeight;
}
#include <vector>
#include <utility>
class twoCats
{
private:
std::vector<cat> cats_;
public:
twoCats (cat theFirstCat)
{ cats_.push_back( std::move( theFirstCat ) ); }
void addSecondCat (cat theSecondCat)
{ cats_.push_back( std::move( theSecondCat ) ); }
};
int main() {return 0;}
Alternatively, you might use boost::optional
.
或者,您可以使用boost::optional
.
Or allocate the instances dynamically (use a smart pointer such as unique_ptr
to manage lifetime then).
或者动态分配实例(然后使用智能指针unique_ptr
来管理生命周期)。
Or, let cats be default-constructible.
或者,让猫默认构造。
As noted by "thang" in a comment, the original design does not guarantee that a twoCats
has two cats. It can have just one cat, or three or more cats. So it would be a good idea to change the design.
正如评论中的“thang”所指出的,原始设计并不能保证 atwoCats
有两只猫。它可以只有一只猫,也可以有三只或更多只猫。所以改变设计是个好主意。
For example, have a constructor that takes two cat arguments, or cat heights.
例如,有一个带有两个 cat 参数或 cat 高度的构造函数。
Or for another example, changing the name of twoCats
.
或者再举一个例子,更改twoCats
.
回答by c-smile
As name of your class (twoCats) states it represents two cats always. These kittens can be alive, dead or even not yet born. But it shall be two of them.
正如您的班级名称 (twoCats) 所述,它始终代表两只猫。这些小猫可以是活的、死的,甚至还没有出生。但应该是他们两个。
Your design is wrong in the sense that either:
您的设计是错误的,因为:
cat
should be able to represent non-born cat (so it should have public default constructor setting the object into non-born state initially) or- your twoCats constructor shall accept exactly two cats at the very beginning.
cat
应该能够代表非出生的猫(因此它应该具有公共默认构造函数,最初将对象设置为非出生状态)或- 你的 twoCats 构造函数在一开始就应该接受两只猫。