在构造函数中,候选者需要1个参数,但提供了0
In constructor, candidate expects 1 argument, 0 provided
这是代码:
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;}
这些是错误:
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
我不理解以下内容:
- 为什么
twoCats
的构造函数试图调用cat
的默认构造函数?当然,它不需要构造cat
的实例,因为当twoCats
初始化时,它将被传递一个已经初始化的cat
实例,该实例将被传递int height
参数 - 为什么同一个错误消息块显示两次?我在Ubuntu 12.04上调用了
g++ main.cpp
您需要一个默认构造函数或在twoCats
构造函数初始化列表中显式初始化cat对象,以避免默认构造。
为什么twoCats的构造函数试图调用默认cat的构造函数?当然,它不需要构造实例当初始化twoCats时,它将被传递一个将被传递int高度的cat的初始化实例论点
它需要为cat
对象构造默认值
private:
cat firstCat;
cat secondCat;
在类twoCats
中,因为您没有初始化它们。在您的构造函数中
cat::cat (int inputHeight)
{
height = inputHeight;
^^^^^^^^^^^^^^^^^^^^
} // this is assignment
这是对已创建对象的分配。
规则如下:如果您没有在ctor
初始化列表中显式初始化实例,则
- 调用默认
ctor
- 最终将指定给
ctor
主体中已默认构造的对象
因此,若并没有在初始化列表中进行初始化,那个么将面临额外调用的惩罚。
C++标准n3337§12.6.2/10初始化基础和成员
在非委托构造函数中,初始化在以下顺序:
--首先并且仅对于最派生类(1.8)的构造函数,虚拟基类按照它们在的有向无环图的深度优先左到右遍历基类,其中"从左到右"是派生类基类说明符列表中的基类。
--然后,直接基类按声明顺序初始化为它们出现在基说明符列表中(无论mem初始化器)。
--然后,按非静态数据成员的顺序初始化在类定义中声明(无论mem初始化器)。
--最后,执行构造函数主体的复合语句。
[注:申报令旨在确保成员子对象的销毁顺序与初始化。--尾注]
这是一个代码演示。
我会这样初始化类twoCats
:
class twoCats
{
private:
cat firstCat;
cat secondCat;
public:
twoCats (const cat& theFirstCat, const cat& theSecondCat)
: firstCat (theFirstCat), secondCat (theSecondCat)
{
}
};
这里的重要部分是构造函数:
后面的冒号。它启动成员初始化列表,如果可能的话,所有类数据成员都应该在该列表中初始化。
数据成员的初始化在C++中是一个相当复杂的问题,我建议你在谷歌上搜索。
特别是,由于您有两个类类型的成员,无论怎样,编译器都会尝试在构造函数中初始化它们。它对每只猫都这样做,这可能是您两次收到错误消息块的原因。在默认情况下,编译器尝试使用默认构造函数(即不带参数的构造函数)初始化cat数据成员。不幸的是,cat
没有默认构造函数,因为您用一个参数声明了一个构造函数。换句话说,每个cat都必须用一个参数初始化(或者在C++11中复制或移动)。
我不建议在没有参数的情况下为cat
声明一个额外的构造函数:似乎没有猫的"默认高度",而另一个答案所建议的-1
非常奇怪:它似乎没有构造一个有效的对象,在使用cat
的任何成员函数之前,都必须检查这个默认值。
编辑:这是从格式的角度来看的。至于程序的语义,复制cat可能是错误的。也许你确实需要一个引用(或指针)来初始化你的两个Cats,也许不需要。
两个cat实例都必须在它们开始存在时进行初始化。
为了避免这种情况,您可以将每个实例的创建推迟到需要的时候
一种简单而安全的方法是使用std::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;}
或者,您可以使用boost::optional
。
或者动态分配实例(然后使用智能指针如unique_ptr
来管理生存期)。
或者,让猫默认为可构造的。
正如"thang"在评论中所指出的,最初的设计并不能保证twoCats
有两只猫。它可以只有一只猫,也可以有三只或更多只猫。因此,更改设计是个好主意。
例如,有一个接受两个cat参数或cat高度的构造函数。
或者,例如,更改twoCats
的名称。
作为类(twoCats)的名称,它表示两个猫始终。这些小猫可以是活的,也可以是死的,甚至还没有出生。但这将是他们中的两个。
你的设计是错误的,要么:
cat
应该能够代表非出生猫(所以它应该有将对象初始设置为非出生状态的公共默认构造函数)或- 你的"两只猫"构造函数一开始就应该接受两只猫
- C++:使用运算符 = 调用多参数构造函数
- 通过零参数构造函数创建的 glm::mat4 应该包含哪些值?
- 好奇的混合与可变参数构造函数
- 具有默认值的单个参数构造函数是否与默认构造函数相同?
- 为什么我们需要创建一个单参数构造函数来使用临时的无名称对象
- 在可变参数构造函数中初始化常量数组
- C++ 显式多参数构造函数歧义
- 零一参数构造函数
- 可变参数构造函数中的 SFINAE
- 当没有显式关键字与单参数构造函数一起使用时,编译器可以发出警告
- 可变参数类模板和可变参数构造函数
- 确保模板参数类型与其可变参数构造函数的类型匹配
- C++默认参数构造函数与内联初始化优先级
- 如何在 c++ 中将包含复制构造函数的类的参数构造函数称为私有?
- 自动存储中没有无参数构造函数的类对象和异常
- 警告:用两个参数构造函数返回对象时,表达结果未使用
- 如何在C++中调用无参数构造函数
- 在 c++ 中具有多个参数构造函数的模板类存在问题
- 可变参数构造函数优先于用户提供的移动构造函数,除非默认
- 如何从可变参数构造函数参数构造任何对象?