目录
1. 作用:
被编译器自动调用,完成对象初始化和清理工作。
如果未提供,则编译器提供的构造函数和析构函数是空实现。
2. 构造函数:初始化
创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无需手动调用。
类名( ) { }
- 构造函数,没有返回值也不写void;
- 函数名称与类名相同;
- 构造函数可以有参数,因此可以发生重载;
- 程序在调用对象时会自动调用构造,无须手动调用,而且只会调用一次。
class Person
{
public:
Person()
{
cout<<"构造函数的调用"<<endl;
}
}
3. 析构函数:清理
对象销毁前系统自动调用,完成清理工作
~ 类名( ) { }
- 析构函数,没有返回值也不写void;
- 函数名称与类名相同,在名称前加上符号~;
- 析构函放不可以有参数,因此不可以发生重载;
- 程序在对象销毁前会自动调用析构,无须手动调用,而且只会调用一次。
class Person
{
public:
~Person()
{
cout<<"析构函数的调用"<<endl;
}
}
构造函数又可以进行分类。
4. 构造函数的分类及调用
- 按参数分为: 有参构造、无参构造(默认构造)
class Person
{
public:
Person()
{
cout<<"无参构造函数的调用"<<endl;
}
Person(int a)
{
cout<<"有参构造函数的调用"<<endl;
}
}
- 按类型分为: 普通构造、拷贝构造
// 拷贝构造函数
class Person
{
public:
Person(const Person &p) //const + 当前类名 + 引用方式传进数据
{
age =p.age;
cout<<"拷贝构造函数的调用"<<endl;
}
}
- 调用方式有: 括号法、显示法、隐式转换法
// 括号法
Person p1; // 默认构造函数
Person p2(10); //有参构造函数
Person p3(p2); //拷贝构造函数
注:使用括号法调用默认构造函数时,不要在最后加(),即Person p1(),因为这句话会被编译器当做函数声明,不会认为在创建对象。
// 显示法
Person p1; // 默认构造函数
Person p2 = Person(10); //有参构造函数
Person p3 = Person(p2); //拷贝构造函数
注:1. Person(10)被称为匿名对象,当前行执行结束后,系统会立即回收掉匿名对象。
2. 不要利用拷贝构造函数,初始化匿名对象,即Person(p3),编译器会认为是对象声明,即创建了一个默认构造函数Person p3。
// 隐式转换法
Person p4 = 10; //有参构造函数
Person p5 = p4; //拷贝构造函数
5. 拷贝构造函数调用
拷贝函数通常在以下三种情况使用:
- 使用一个已经创建完毕的对象来初始化一个新对象
void test01()
{
Person p1(20); // 有参构造
Person p2(p1); // 拷贝构造
}
- 值传递的方式给函数参数传值
void doWork(Person p)
{
//值传递的方式给函数参数传值
}
void test02()
{
Person p; // 默认构造
doWork(p); // 拷贝构造
}
- 以值方式返回局部对象
void doWork2()
{
// 默认构造函数调用:
Person p1; //局部对象
// 拷贝构造函数调用:
return p1; //值方式返回,不会返回Person p1,会拷贝一个新的对象temp返回给外边
// 析构函数调用:
}
void test03()
{
Person p = doWork2(); // 拷贝构造,相当于Person p = Person temp
// 析构函数调用:
}