在其他 class 构造函数中使用 class 作为类型
Use class as type in other class constructor
我想在另一个 class 矩形中使用 class 点。
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 class 的构造函数方法使用两个 Point 类型的参数来实例化一个 Rect 对象。我想我不能使用“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()
。
但是 问题 是因为你的 class Point
有 user-defined 构造函数,编译器不会合成 默认构造函数 Point::Point()
.
有两种方法可以解决这个问题。
解决方案 1
首先,您可以为 class 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
。
解决方案 2
我们还可以在构造函数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){
}
};
成员在构造函数主体运行之前被初始化。当你写:
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
创建默认构造函数,这是因为您声明了另一个构造函数。这禁止编译器生成自己的默认构造函数(没有像第一种选择那样被告知这样做)。
我想在另一个 class 矩形中使用 class 点。
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 class 的构造函数方法使用两个 Point 类型的参数来实例化一个 Rect 对象。我想我不能使用“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()
。
但是 问题 是因为你的 class Point
有 user-defined 构造函数,编译器不会合成 默认构造函数 Point::Point()
.
有两种方法可以解决这个问题。
解决方案 1
首先,您可以为 class 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
。
解决方案 2
我们还可以在构造函数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){
}
};
成员在构造函数主体运行之前被初始化。当你写:
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
创建默认构造函数,这是因为您声明了另一个构造函数。这禁止编译器生成自己的默认构造函数(没有像第一种选择那样被告知这样做)。