目录
[1. 无参构造函数](#1. 无参构造函数)
[2. 全缺省构造函数](#2. 全缺省构造函数)
一、为什么需要构造函数?
在C++中,我们用类创建对象。
例如定义一个日期类:
cpp
class Date {
public:
void Print() {
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
如果直接创建对象:
cpp
Date d;
d.Print();
这时 _year、_month、_day没有被初始化,可能是随机赋值。
所以我们需要一种机制,在对象创建时自动完成初始化。
这就是构造函数的作用。
二、什么是构造函数?
构造函数时类中的一种特殊成员函数。
它的作用是:
在对象创建时自动调用,用来初始化对象。
构造函数的基本特点:
cpp
1. 函数名和类名相同;
2. 没有返回值;
3. 对象实例化时自动调用;
4. 构造函数可以重载。
例如:
cpp
#include <iostream>
using namespace std;
class Date {
public:
Date() {
_year = 2024;
_month = 1;
_day = 1;
}
void Print() {
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main() {
Date d;
d.Print();
return 0;
}
运行结果:
cpp
2024-1-1
当执行:
cpp
Date d;
对象 d 创建时,构造函数 Date() 会自动调用。
三、构造函数不是创建对象
构造函数名字里有"构造",但他并不是负责开辟空间的。
对象空间由编译器根据类的成员变量自动分配。
构造函数真正负责的是:
cpp
初始化对象中的成员变量。
比如:
cpp
Date d;
这一步会创建对象空间。
随后构造函数会自动执行,把 _year、_month、_day 设置成初始值。
四、带参数的构造函数
构造函数也可带参数:
cpp
#include <iostream>
using namespace std;
class Date {
public:
Date(int year, int month, int day) {
_year = year;
_month = month;
_day = day;
}
void Print() {
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main() {
Date d(2025, 5, 16);
d.Print();
return 0;
}
运行结果:
cpp
2025-5-16
这里:
cpp
Date d(2025, 5, 16);
创建对象时,会自动调用带三个参数的构造函数。
五、构造函数支持重载
构造函数也可以重载。
因为构造函数的函数名都可以和类名相同,所以能否构成重载主要看参数列表是否支持。
例如:
cpp
class Date {
public:
Date() {
_year = 2024;
_month = 1;
_day = 1;
}
Date(int year, int month, int day) {
_year = year;
_month = month;
_day = day;
}
void Print() {
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
使用时:
cpp
Date d1;
Date d2(2025, 5, 16);
d1 调用无参构造函数,d2 调用带参构造函数。
六、默认构造函数
默认构造函数时指不需要传参就可以调用的构造函数。
常见的有三种形式:
cpp
1. 编译器自己是生成的默认构造函数;
2. 用户自己写的无参构造函数;
3. 用户自己写的全缺省构造函数。
1. 无参构造函数
cpp
Date() {
_year = 2024;
_month = 1;
_day = 1;
}
调用:
cpp
Date d;
注意,无参构造函数创建对象不要写成:
cpp
Date d();
这不是创建对象,而容易被编译器理解成函数声明。
2. 全缺省构造函数
cpp
Date(int year = 2024, int month = 1, int day = 1) {
_year = year;
_month = month;
_day = day;
}
这种构造函数既可以不传参,也可以传部分参数或全部传参。
cpp
Date d1;
Date d2(2025);
Date d3(2025, 5);
Date d4(2025, 5, 16);
全缺省构造函数比较灵活。
七、无参构造和全缺省构造不能同时存在
下面这种写法会出问题:
cpp
class Date {
public:
Date() {
_year = 2024;
_month = 1;
_day = 1;
}
Date(int year = 2024, int month = 1, int day = 1) {
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
因为当我们写:
cpp
Date d;
编译器会发现:
cpp
无参构造函数可以调用;
全缺省构造函数也可以不传参调用。
这样就产生了歧义,编译器不知道应该调用哪一个。
所以要记住:
无参构造函数和全缺省构造函数不能同时存在。
八、编译器自动生成的默认构造函数
如果我们没有写任何构造函数,编译器会生成一个默认的构造函数。
例如:
cpp
class Date {
private:
int _year;
int _month;
int _day;
};
这时可以写:
cpp
Date d;
但是要注意:
编译器自动生成的默认构造函数,对内置类型成员变量一般不会初始化。
比如 int、char、double 这类内置类型,仍然可能是随机值。
九、自己写了构造函数后,编译器还会生成默认构造函数吗?
如果用户显示写了任意构造函数,编译器就不会子自动生成默认构造函数。
例如:
cpp
class Date {
public:
Date(int year, int month, int day) {
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
这时如果写:
cpp
Date d;
就会报错。
因为你已经写了带参构造函数,编译器不会再自动生成无参默认构造函数。
如果你想创建无参对象,就需要自己再写一个无参构造函数,或者使用全缺省构造函数。
十、小结
本篇主要学习了C++中的构造函数。
需要记住:
- 构造函数是特殊的成员函数;
- 构造函数名必须和类名相同;
- 构造函数没有返回值;
- 构造函数在对象创建时自动调用;
- 构造函数的主要作用是初始化对象;
- 构造函数可以重载;
- 默认构造函数是不需要传参就能调用的构造函数;
- 无参构造函数和全缺省构造函数不能同时存在;
- 如果用户自己写了构造函数,编译器不会再自动生成默认构造函数;
- 编译器自动生成的默认构造函数一般不会初始化内置类型成员。
构造函数是类和对象部分的重点内容,后面学习析构函数、拷贝构造函数、运算符重载时都会继续用到。