我想在其他类 Rect 中使用类 Point。
class Point
{
int x, y;
public:
Point (int px, int py){
x = px;
y = py;
}
};
class Rect
{
Point top_left;
Point bottom_right;
public:
Rect (Point p1, Point p2){
top_left = p1;
bottom_right = p2;
}
};
错误消息是:“main.cpp:31:30:错误:没有匹配的函数可用于调用‘Rect::Point::Point()’”。根据我的理解, Rect 类的构造函数方法使用两个 Point 类型的参数来实例化 Rect 对象。我想我不能使用“Point”作为类型,因为它听起来像是编译器想要调用一个函数。错误消息对我没有帮助,所以我希望你能帮我。提前感谢您。
成员在构造函数主体运行之前初始化。当你写下:
Rect (Point p1, Point p2){
top_left = p1;
bottom_right = p2;
}
然后在执行构造函数之前,成员
top_left
和 bottom_right
被初始化。由于 Point
没有默认构造函数,因此无法初始化成员。
要使用构造函数初始化成员,您应该使用成员初始值设定项列表:
Rect (Point p1, Point p2) : top_left(p1), bottom_right(p2) { }
也可以通过为成员提供默认初始化器来防止错误:
class Rect
{
Point top_left{0,0};
Point bottom_right{0,0};
public:
Rect (Point p1, Point p2){
top_left = p1;
bottom_right = p2;
}
};
或者为
Point
提供默认构造函数。默认构造函数是可以不带参数调用的构造函数。但是,无论如何,您应该更喜欢成员初始值设定项列表而不是构造函数主体中的赋值,因为初始化 + 赋值比仅初始化更昂贵。
问题在于,当创建
Rect
对象时,成员变量是在执行 Rect
构造函数体之前构造并初始化的。
由于
Point
成员变量没有显式初始化,因此它们需要默认可构造,但事实并非如此,因为您没有默认的 Point
构造函数。
有几种可能的解决方案,其中最简单的一种是:
创建一个
Point
默认构造函数。它不必执行任何操作,并且可以由编译器生成(但您仍然必须告诉编译器生成它):
class Point
{
public:
Point() = default;
...
};
虽然现在可以默认构造
Point
,但它会使 x
和 y
成员未初始化。
但我宁愿推荐另一种解决方案:
创建
Rect
构造函数初始值设定项列表来初始化Rect
的成员变量:
class Rect
{
Point top_left;
Point bottom_right;
public:
Rect(Point p1, Point p2)
: top_left(p1), bottom_right(p2)
{
// Empty
}
...
};
使用第二种解决方案,不需要
Point
默认构造函数。
至于为什么
Point
没有创建默认构造函数,那是因为你声明了另一个构造函数。这会禁止编译器生成自己的默认构造函数(而不像第一个替代方案那样被告知这样做)。
在您给定的示例中,数据成员
top_left
和 bottom_right
在执行 Rect::Rect (Point, Point)
的主体之前已进行 默认初始化。这意味着在您的语句示例中:
Point top_left; //this statement needs default ctor in your example because this data member is default initialized
Point bottom_right;//this statement needs default ctor in your example because this data member is default initialized
要工作,需要默认构造函数
Point::Point()
。
但问题是,由于您为类
Point
用户定义了构造函数,编译器将不会合成默认构造函数Point::Point()
。
有2种方法可以解决这个问题。
首先,您可以为类
Point
添加默认构造函数,如下所示:
class Point
{
int x, y;
public:
Point (int px, int py){
x = px;
y = py;
}
//default constructor
Point(): x(0), y(0){
}
};
工作演示。
在上面修改后的代码中,我添加了一个默认构造函数,它使用 构造函数初始值设定项列表 来初始化数据成员
x
和 y
。
我们还可以在构造函数Rect::Rect(Point, Point)
中使用
构造函数初始化列表通过传递参数来初始化数据成员,而不是默认初始化它们。
class Rect
{
Point top_left;
Point bottom_right;
public:
//use constructor initializer list to intialize the data members by passing arguments instead of default initializing them
Rect (Point p1, Point p2): top_left(p1), bottom_right(p2){
}
};
工作演示。