默认构造函数
默认构造函数:是无参调用的构造函数,包括两种:
- 没有参数
- 每个参数有初始值
- 默认初始化:在不使用初始化器构造变量时执行的初始化。
- 值初始化:在以空初始化器构造对象时进行的初始化
由来
先看下面代码
代码内容很简单,定义了一个包含成员x,y的类Point。在序列的地方可以使用这个类
虽然我们并没有定义Point类的构造函数,我们依然可以定义Point类的pt对象并使用它,其原因是编译器会自动生成一个缺省的构造函数,其效果相当于
但是,一旦添加了其他有参数的构造函数,编译器就不再生成缺省的构造函数了
C++11的解决方案
C++11允许我们使用=default
来要求编译器生成一个默认构造函数:
这样,我们就可以继续我们的美好生活了。
#include <stdio.h>
struct Point {
Point() = default;
Point(int _x, int _y) : x(_x), y(_y){
}
int x;
int y;
};
int main() {
Point point;
printf("%d, %d", point.x, point.y);
}
如果是自己编写的无参构造函数的话,就需要指定成员的构造方式。默认构造函数会对数据成员进行默认初始化,不需要另外指定。这样可以省去一些麻烦。
由于整数是内置类型,而整数成员的默认初始化是不初始化,所以本例中的x,y还是需要类内初始化。这是另一个话题。
语法
语法:
语法 | 说明 | o |
---|---|---|
类名 ( ) ; |
(1) | |
类名 :: 类名 ( ) 函数体 |
(2) | |
类名() = delete ; |
(3) | C++11起 |
类名() = default ; |
(4) | C++11起 |
类名 :: 类名 ( ) = default ; |
(5) | C++11起 |
其中类名
必须指名当前类(或类模板的当前实例化),或在命名空间作用域或友元声明中声明时,必须是有限定的类名。
- 类定义中的默认构造函数声明
struct Point {
Point(){
x = 0;
y = 0;
};
int x;
int y;
};
- 类定义之外的默认构造函数的定义(该类必须包含一条声明1)
struct Point {
Point(); //声明1
int x;
int y;
};
Point::Point(){
x = 10;
y = 0;
};
- 弃置的默认构造函数:若其被
重载决议
所选择,则程序编译失败。
struct Point {
Point() = delete ; // 错误:使用了被删除的函数‘Point::Point()’
int x;
int y;
};
- 预置的默认构造函数:即便其他构造函数存在,在某些情况下编译器会定义的隐式默认构造函数。
#include <stdio.h>
struct Point {
Point() = default;
Point(int _x, int _y) : x(_x), y(_y){
}
int x;
int y;
};
int main() {
Point point;
printf("%d, %d", point.x, point.y);
}
5. 类定义之外的预置的默认构造函数(该类必须包含一条声明 (1))。这种构造函数被当做是用户提供的(user-provided)(见下文以及值初始化)。
struct Point {
Point() ; // 错误:使用了被删除的函数‘Point::Point()’
int x;
int y;
};
Point::Point() = default;
隐式声明的默认构造函数
- 若不对类类型(struct、class 或 union)提供任何用户声明的构造函数,则编译器将始终声明一个作为其类的 inline public 成员的默认构造函数。
#include <stdio.h>
struct Point1 {
int x;
int y;
};
class Point2 {
public:
int x;
int y;
};
union Point3 {
int x;
int y;
};
int main() {
Point1 point1;
Point2 point2;
Point3 point3;
printf("%d, %d\n", point1.x, point1.y);
printf("%d, %d\n", point2.x, point2.y);
printf("%d, %d\n", point3.x, point3.y);
}
- C++11起,当存在用户声明的构造函数时,用户仍可以关键词 default 强制编译器自动生成原本隐式声明的默认构造函数。
#include <stdio.h>
struct Point1 {
Point1() = default; // 必须,当用户最定义了有参构造函数时编译器不会自己生成默认构造函数
Point1(int _x, int _y) : x(_x), y(_y){
}
int x;
int y;
};
class Point2 {
public:
Point2() = default; // 必须,当用户最定义了有参构造函数时编译器不会自己生成默认构造函数
Point2(int _x, int _y) : x(_x), y(_y){
}
int x;
int y;
};
union Point3 {
Point3() = default; // 必须,当用户最定义了有参构造函数时编译器不会自己生成默认构造函数
Point3(int _x) : x(_x){
}
int x;
int y;
};
int main() {
Point1 point1;
Point2 point2;
Point3 point3;
printf("%d, %d\n", point1.x, point1.y);
printf("%d, %d\n", point2.x, point2.y);
printf("%d, %d\n", point3.x, point3.y);
}
实例
class A
{
public:
A(); //没有参数
};
class B
{
public:
explicit B(int x = 1, bool b = true); //每个参数有初始值
//explicit:阻止执行隐式转换,但是可以显示类型转换
};
class C
{
public:
explicit C(int c); //非默认构造函数
};
struct A
{
int x;
A(int x = 1): x(x) {
} // 用户定义默认构造函数
};
struct B: A
{
// 隐式定义 B::B(),调用 A::A()
};
struct C
{
A a;
// 隐式定义 C::C(),调用 A::A()
};
struct D: A
{
D(int y): A(y) {
}
// 不会声明 D::D(),因为存在另一构造函数
};
struct E: A
{
E(int y): A(y) {
}
E() = default; // 显式预置,调用 A::A()
};
struct F
{
int& ref; // 引用成员
const int c; // const 成员
// F::F() 被隐式定义为弃置
};
int main()
{
A a;
B b;
C c;
// D d; // 编译错误
E e;
// F f; // 编译错误
}
https://author.baidu.com/home?from=bjh_article&app_id=1597683592389912