文章目录
构造函数和析构函数
对象的初始化和清理是两个非常重要的安全问题:
- 一个对象或者变量没有初始状态,对其使用后果是未知的;
- 使用完一个对象或变量,没有及时清理,也会造成一定的安全问题。
c++可以利用构造函数和析构函数解决上述问题。在两个函数会被编译器自动调用。对象的初始化和清理工作是编译器强制要做的,当我们不提供构造函数和析构函数时,编译器会提供空的构造函数和析构函数。
构造函数:主要作用在创建对象时为对象的成员属性赋值。
析构函数:主要作用在对象销毁前系统自动调用,执行一些清理工作。
构造函数语法:类名() {}
- 构造函数,没有返回值也不写void
- 函数名称与类名相同
- 构造函数可以有参数,因此可以发生重载
- 程序在调用对象时会自动调用构造,而且只会调用一次
析构函数语法:~类名() {}
- 构造函数,没有返回值也不写void
- 函数名称与类名相同,在名称前加上符号~
- 构造函数不可以有参数,因此不可以发生重载
- 程序在对象销毁前会自动调用构造,而且只会调用一次
构造函数的分类和调用
两种分类方式:
- 按参数分为:有参构造和无参构造
- 按类型分为:普通构造和拷贝构造
//无参构造
Person() (默认构造)
{
cout << “无参构造函数的调用” << endl;
}
//有参构造
Person(int a)
{
age = a;
cout << “有参构造函数的调用” << endl;
}
//拷贝构造函数
Person(const Person &p)
{
//从形参列表中传入一个对象的所有属性拷贝到本对象身上
age = p.age;
cout << “拷贝构造函数的调用” << endl;
}
三种调用方式:括号法、显示法、隐式转换法
- 括号法:
Person p2(10); //调用的是有参构造函数
Person p3(p2); //调用的是拷贝构造函数
注意:调用默认构造函数时,不要加(),比如:Person p1(); 编译器会认为是一个函数的声明,不会认为是在创建对象
- 显示法:
//2、显示法
Person p1; //默认调用的是无参构造函数
Person p2 = Person(10); //调用的是有参构造函数
Person p3 = Person(p2); //调用的是拷贝构造函数
Person(10); //匿名对象 特点:当前这行代码执行结束后,系统会立即回收掉匿名对象
- 隐式转换法:
//3、隐式转换法
Person p4 = 10; //相当于写了 Person p4 = Person(10); 和 Person p4(10);
Person p5 = p4; //相当于写了 Person p5 = Person(p4); 和 Person p5(p4);
class Person
{
public:
//1.构造函数
Person() //无参构造(默认构造)
{
cout << "无参构造函数的调用" << endl;
}
Person(int a) //有参构造
{
age = a;
cout << "有参构造函数的调用" << endl;
}
Person(const Person &p) //拷贝构造函数
{
//从形参列表中传入一个对象的所有属性拷贝到本对象身上
age = p.age;
cout << "拷贝构造函数的调用" << endl;
}
int age;
};
//调用构造函数
void test1()
{
1、括号法
//Person p1; //默认调用的是无参构造函数
//Person p2(10); //调用的是有参构造函数
//Person p3(p2); //调用的是拷贝构造函数
//cout << "p2的年龄是:" << p2.age << endl;
//cout << "p3的年龄是:" << p3.age << endl;
注意:调用默认构造函数时,不要加(),比如:Person p1(); 编译器会认为是一个函数的声明,不会认为在创建对象
//2、显示法
Person p1; //默认调用的是无参构造函数
Person p2 = Person(10); //调用的是有参构造函数
Person p3 = Person(p2); //调用的是拷贝构造函数
Person(10); //匿名对象 特点:当前这行代码执行结束后,系统会立即回收掉匿名对象
//3、隐式转换法
Person p4 = 10; //相当于写了 Person p4 = Person(10); 和 Person p4(10);
Person p5 = p4; //相当于写了 Person p5