我最近开始学习C ++并且一直在使用cplusplus.com的教程来学习。我进入了类部分,看到了如何初始化成员而不在构造函数的主体中键入它。起初这看起来很简单,但他们的例子让我很困惑。这是:
// member initialization
#include <iostream>
using namespace std;
class Circle {
double radius;
public:
Circle(double r) : radius(r) { }
double area() {return radius*radius*3.14159265;}
};
class Cylinder {
Circle base;
double height;
public:
Cylinder(double r, double h) : base (r), height(h) {}
double volume() {return base.area() * height;}
};
int main () {
Cylinder foo (10,20);
cout << "foo's volume: " << foo.volume() << '\n';
return 0;
}
困扰我的部分是Cylinder类,具体来说是:
Cylinder(double r, double h) : base (r), height(h) {}
在该类的早期,声明了一个名为Circle的“base”的成员对象。然后,在圆柱构造函数中,这个“基础”对象被设置为“r”,这是一个双重的:
base (r), height(h) {}
我的问题是,当它是“Circle”类型时,如何将成员“base”初始化为double?另外,我尝试做的事情(我认为)本质上是相同的,但我在构造函数的主体中初始化了“base”:
Cylinder(double r, double h)
{
base = r;
height = h;
}
这给我留下了编译错误:“错误:没有匹配函数来调用'Circle :: Circle()'”
如果有人能为我解决这个困惑,我会非常感激。感谢。
答案 0 :(得分:2)
会员&#34; base&#34;当它是&#34; Circle&#34;?
时,被初始化为double
成员初始化列表将调用base
的相应构造函数,Circle
有一个构造函数,其中double
作为参数,因此它可以正常工作。
base = r;
也会编译,因为r
可以通过上面的构造函数隐式转换为Circle
,然后将调用operator=(const Circle&)
(由编译器隐式生成)。但是没有成员初始化列表base
需要首先由默认构造函数初始化,Circle
没有。那是什么错误信息。
答案 1 :(得分:0)
在成员初始化列表中查看此link。特别是以下内容适用于您的情况:
1)使用直接初始化初始化由class-or-identifier命名的基类或成员,如果expression-list为空,则初始化值初始化
和
在构成构造函数体的复合语句开始执行之前,完成所有直接碱基,虚拟碱基和非静态数据成员的初始化。成员初始化列表是可以指定这些对象的非默认初始化的地方。
特别是在您的示例中,类型base
的{{1}}在成员初始值设定项列表中使用Circle
进行了直接初始化。但如果成员初始值设定项列表中未显示double
,则默认初始化。但是,编译器不会为类base
合成默认构造函数,因为还有其他用户定义的构造函数。这就是为什么你看到错误:“错误:没有匹配函数来调用'Circle :: Circle()”
您可以使用Circle
= default
答案 2 :(得分:0)
Cylinder(double r, double h) : base (r), height(h) {}
上面的代码使用初始化列表构造对象,&#34; base(r),height(h)&#34;,这是base的初始化真正发生的地方:base的构造函数被调用。
如果你将base放入构造函数体中,就像这样:
Cylinder(double r, double h)
{
base = r;
height = h;
}
由于初始化列表中没有任何内容,但是在此阶段必须进行base的初始化,编译器会调用base的no-parameter构造函数来执行此操作。但是你没有提供这样的构造函数,而是一个带有一个参数的构造函数,在这种情况下,编译器也不会生成没有参数的构造函数,因此编译器无法找到没有参数的base的构造函数,并且会引发错误。< / p>
要解决此问题,您只需要提供一个没有Circle类参数的构造函数:
class Circle {
double radius;
public:
Circle(double r) : radius(r) { }
Circle():radius(1.0){} // just example
double area() {return radius*radius*3.14159265;}
};
然后你的代码就行了。但是你可能需要注意&#34; base = r&#34;在Cylinder的构造函数体中:
关于会员&#34;身高&#34;在Cylingder中,因为它是原始类型,通常可以在初始化列表中初始化它,或者将它保留在内存中,然后在Cylinder的构造函数体中为它指定一个值。但如果你想让&#34;身高&#34;在转到构造函数体之前已经确定了值,你必须在初始化中初始化它