构造函数
构造函数完成对象的初始化工作。
构造函数分为三种:
1.自己不写编译器自动生成的默认无参构造函数
2.自己写的无参构造函数
3.自己写的全缺省构造函数
当自己实现了构造函数,编译器不会再调用默认的无参构造函数。
建议写全缺省的构造函数,因为全缺省的构造函数既可以传参数,也可以不传参数,表示的范围更广。编译器默认生成的构造函数对于内置类型的变量不会初始化,但对于自定义类型的成员对象会调用他的构造函数。(C++11 中针对内置类型成员不初始化的缺陷,又打了补丁置类型成员变量在类中声明时可以给默认值)
class Time
{
public:
Time()
{
cout << "Time()" << endl;
_hour = 0;
_minute = 0;
_second = 0;
}
private:
int _hour;
int _minute;
int _second;
};
class Date
{
private:
// 基本类型(内置类型)
int _year = 1970;
int _month = 1;
int _day = 1;
// 自定义类型
Time _t;
};
int main()
{
Date d;
return 0;
}
析构函数
析构函数完成对象的清理工作。(不是完成对象的销毁)
当一个对象结束他的生命周期时会调用析构函数。一个对象只有一个析构函数,若自己没有写析构函数,编译器会自动生成默认的析构函数,对于自定义类型的成员对象,析构时编译器会调用成员对象的析构函数。
class Time
{
public:
~Time()
{
cout << "~Time()" << endl;
}
private:
int _hour;
int _minute;
int _second;
};
class Date
{
private:
// 基本类型(内置类型)
int _year;
int _month;
int _day;
// 自定义类型
Time _t;
};
int main()
{
Date d;
return 0;
}
如果类中没有申请内存时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如Data类,有内存申请时,一要写,否则会造成内存泄漏,比如Stack类。
class Stack {
private:
int* _a;
int _size;
int _capacity;
public:
Stack(int size=10) {
_a = new int[size];
_size = 0;
_capacity = size;
}
~Stack() {
if (_a!=nullptr) {
free(_a);
_size = _capacity = 0;
}
}
};
int main() {
Stack st;
return 0;
}
拷贝构造函数
拷贝构造函数的参数只有一个且比需是类类型对象的引用,还必须加上const ,防止修改引用的对象和满足const对象可以调用。若不使用引用,使用传值的方式编译器会直接报错,因为引起无穷递归。
class Date
{
private:
int _year;
int _month;
int _day;
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
// Date(const Date d) // 错误写法:编译报错,会引发无穷递归
Date(const Date& d) //正确写法
{
_year = d._year;
_month = d._month;
_day = d._day;
}
};
int main()
{
Date d1;
Date d2(d1);
return 0;
}
类中如果没有涉及内存申请时,拷贝构造写不写都行;如果有内存申请,拷贝构造一定要写,否则会引起浅拷贝问题。解决方法请看另一篇博客浅拷贝与深拷贝-CSDN博客