在其他类构造函数中使用类作为类型[重复]

问题描述 投票:0回答:3

我想在其他类 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”作为类型,因为它听起来像是编译器想要调用一个函数。错误消息对我没有帮助,所以我希望你能帮我。提前感谢您。

c++ class constructor
3个回答
5
投票

成员在构造函数主体运行之前初始化。当你写下:

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
提供默认构造函数。默认构造函数是可以不带参数调用的构造函数。但是,无论如何,您应该更喜欢成员初始值设定项列表而不是构造函数主体中的赋值,因为初始化 + 赋值比仅初始化更昂贵。


4
投票

问题在于,当创建

Rect
对象时,成员变量是在执行
Rect
构造函数体之前构造并初始化的。

由于

Point
成员变量没有显式初始化,因此它们需要默认可构造,但事实并非如此,因为您没有默认的
Point
构造函数。

有几种可能的解决方案,其中最简单的一种是:

  1. 创建一个

    Point
    默认构造函数。它不必执行任何操作,并且可以由编译器生成(但您仍然必须告诉编译器生成它):

    class Point
    {
    public:
        Point() = default;
        ...
    };
    

    虽然现在可以默认构造

    Point
    ,但它会使
    x
    y
    成员未初始化。

但我宁愿推荐另一种解决方案:

  1. 创建

    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
没有创建默认构造函数,那是因为你声明了另一个构造函数。这会禁止编译器生成自己的默认构造函数(而不像第一个替代方案那样被告知这样做)。


-2
投票

在您给定的示例中,数据成员

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种方法可以解决这个问题。

解决方案1

首先,您可以为类

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){
       
    }
};

工作演示

© www.soinside.com 2019 - 2024. All rights reserved.