2015-07-03 108 views
2

我正在练习我的面向对象,我有以下类:点和圆。具体来说,Circle有一个中心点和一个半径。下面是相关代码:没有匹配函数调用类构造函数

// Point.h 
class Point 
{ 
    public: 
     Point(double x, double y); 
     double x() const; 
     double y() const; 
     std::string as_string() const; 

    private: 
     double x_coord; 
     double y_coord; 
}; 

// Circle.h 
class Circle 
{ 
    public: 
     Circle(const Point& center, double radius); 
     Point center() const; 
     double radius() const; 
     std::string as_string() const; 
     std::string equation() const; 

    private: 
     Point center_pt; 
     double radius_size; 
}; 

// Circle.cpp 
Circle::Circle(const Point& center, double radius) 
{ 
    center_pt = center; 
    radius_size = radius; 
} 

然而,当我尝试编译这段代码,我得到以下错误:

Circle.cpp: In constructor ‘Circle::Circle(const Point&, double)’: 
Circle.cpp:3: error: no matching function for call to ‘Point::Point()’ 
Point.h:10: note: candidates are: Point::Point(double, double) 
Point.h:8: note:     Point::Point(const Point&) 

我不知道如何解释这个错误。它是否告诉我,我需要在Circle构造函数中为Point参数提供x_coord和y_coord?

+0

明确定义为类点默认构造函数。 –

回答

7

成员center_pt正在默认初始化,这样的操作将调用无参数默认构造函数Point()。然而,这并不是在Point类中定义的,因此会给你带来的错误。

Circle::Circle(const Point& center, double radius) 
{ 
    center_pt = center; //<-- this is an assignment 
         //default init has already occurred BEFORE this point 
    radius_size = radius; 
} 

在这里您可以指定center_pt之前,您需要分配给某个东西。因此编译器会在尝试执行分配之前尝试默认初始化center_pt

相反,如果使用member initializer list就可以避免默认的构造,然后分配问题:

Circle::Circle(const Point& center, double radius): 
    center_pt(center), 
    radius_size(radius) 
{ 
} 

当你创建一个类,你基本上撇开存储到各个成员存储类中。因此,想象一下center_ptradius_size作为内存中的这些值存储在您的类的每个实例中的位置。当你创建一个类时,那些变量必须得到一些默认值,如果你没有指定任何东西,你会得到默认的构造值,不管它们是什么。您可以稍后将值分配给这些位置,但一些初始化将始终发生在创建类时。如果您使用初始化程序列表,您可以明确指定第一次放置在内存中的内容。

通过在此处使用成员初始值设定项列表,您的成员将在第一次正确构建。它还具有节省一些不必要的操作的好处。

+0

谢谢。因此,当我在进入构造函数体之前初始化成员时,编译器是否“将其放在加力燃烧器上”这么说,就构建center_pt而言? – nonremovable

+1

当你创建一个类时,你基本上将存储器放在内存中以存储该类中的各个成员。因此,想象一下'center_pt'和'radius_size'作为内存中那些值被存储的位置。当你创建一个类的时候,这些变量必须得到一些默认值,如果你没有指定任何东西默认的构造值,无论这些值是什么。您可以稍后分配值,但第一个默认值将始终放置在那里。如果您使用初始化程序列表,您可以指定第一次放置在内存中的内容。 – shuttle87

+0

谢谢,这是完全合理的。 – nonremovable

5

变化的构造方式如下

Circle::Circle(const Point& center, double radius) 
    : center_pt(center), radius_size(radius) 
{ 
} 

的问题是,如果你不显式调用与Point类参数的构造函数,则编译器试图调用类的默认构造函数来创建数据成员在您可以在类Circle的构造函数的主体内分配点之前,您可以使用类Circle的center_pt。但是您没有定义类Point的默认构造函数,编译器发出错误。

另一种方法确实是定义类Point的默认构造函数,例如用零初始化点。

考虑到通过设计类Point,您不能更改已创建对象的数据成员coord_xcoord_y。也许您应该重新设计类。

1

变化

Circle::Circle(const Point& center, double radius) 
{ 
    center_pt = center; 
    radius_size = radius; 
} 

Circle::Circle(const Point& center, double radius) : center_pt(center), radius_size(radius) 
{ 
} 

,以便它使用您为点定义的构造函数。

1

这是因为您没有初始化初始化列表中的成员,而是在主体中分配给它。因此,它首先使用默认的ctor构造它,因此也是编译器的抱怨。

考虑更改的事情:

// Circle.cpp 
Circle::Circle(const Point& center, double radius) : 
    center_pt(center), 
    radius_size(radius) 
{ 

} 
相关问题