13.7 - 非静态成员初始化
当编写具有多个构造函数(即大多数构造函数)的类时,在每个构造函数中都为所有成员指定默认值会产生冗余代码,而且如果更新成员的默认值,则需要修改所有的构造函数。
可以直接给普通的类成员变量(那些不使用static关键字的变量)一个默认初始化值:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | #include <iostream>
class Rectangle
{
private:
double m_length{ 1.0 }; // m_length 具有默认值 1.0
double m_width{ 1.0 }; // m_width 具有默认值 1.0
public:
void print()
{
std::cout << "length: " << m_length << ", width: " << m_width << '\n';
}
};
int main()
{
Rectangle x{}; // x.m_length = 1.0, x.m_width = 1.0
x.print();
return 0;
}
|
程序输出结果:
非静态成员初始化(也称为类内成员初始化)为成员变量提供默认值,如果构造函数不为成员本身提供初始化值(通过成员初始化列表),则构造函数将使用这些默认值。
不过,决定对象创建的仍然是构造函数。考虑下面的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 | #include <iostream>
class Rectangle
{
private:
double m_length{ 1.0 };
double m_width{ 1.0 };
public:
// 注意:没有默认构造函数
Rectangle(double length, double width)
: m_length{ length },
m_width{ width }
{
// m_length 和 m_width 会被构造函数初始化(不会使用它们的默认值)
}
void print()
{
std::cout << "length: " << m_length << ", width: " << m_width << '\n';
}
};
int main()
{
Rectangle x{}; // 无法编译,因为不存在默认构造函数,即使成员具有默认值
return 0;
}
|
尽管我们为所有成员提供了默认值,但由于没有提供默认构造函数,因此无法创建不带参数的 Rectangle 对象。
如果提供了默认初始化值,且构造函数通过成员初始化列表初始化成员,则优先使用成员初始化列表。下面的例子说明了这一点:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 | #include <iostream>
class Rectangle
{
private:
double m_length{ 1.0 };
double m_width{ 1.0 };
public:
Rectangle(double length, double width)
: m_length{ length },
m_width{ width }
{
// m_length 和 m_width 会被构造函数初始化(不会使用它们的默认值)
}
Rectangle(double length)
: m_length{ length }
{
// m_length 被构造函数初始化
// m_width 则使用默认值 1.0
}
void print()
{
std::cout << "length: " << m_length << ", width: " << m_width << '\n';
}
};
int main()
{
Rectangle x{ 2.0, 3.0 };
x.print();
Rectangle y{ 4.0 };
y.print();
return 0;
}
|
| length: 2.0, width: 3.0
length: 4.0, width: 1.0
|
注意,使用非静态成员初始化来初始化成员需要使用等号或大括号(统一)初始化式——圆括号初始化形式在这里不起作用:
| class A
{
int m_a = 1; // ok (拷贝初始化)
int m_b{ 2 }; // ok (大括号初始化)
int m_c(3); // 无效 (圆括号初始化)
};
|
COPY
法则
推荐使用非静态成员初始化来为成员变量提供默认值。