内容纲要
对象的初始化和清理
对象的 初始化和清理 是两个非常重要的安全问题
- c++ 利用 构造函数 和 析构函数 解决上述问题,这两个函数编译器会自动调用,完成对象初始化和清理工作。
- 编译器会提供默认的空实现 的构造函数和 析构函数
构造函数:主要用于在创建对象时 为对象的成员属性赋值,构造函数由编译器自动调用,无须手动调用。
析构函数:主要用于对象销毁前系统自动调用,执行一些清理工作
构造函数语法: 类名() {}
- 构造函数,没有返回值 也不写 void;
- 函数名和类名相同;
- 构造函数可以有参数,因此可以发生重载;
- 程序在调用对象时会自动调用构造函数,无需手动调用,且只自动调用一次。
析构函数语法: ~类名() {}
- 析构函数,没有返回值也不写void;
- 函数名称与类名相同,在名称前加上符号
~
; - 析构函数不可以有参数,因此不能发生重载;
- 程序在销毁对象前会自动调用析构,无需手动调用,而且只会调用一次。
注意:对象的生命周期。
#include <iostream>
#include "string"
using namespace std;
class Person
{
public:
Person() {
cout << "Person 构造函数被调用" << endl;
}
int age;
string name;
Person(int x) {
age = x;
cout << "Person 构造函数重载,传入age;其中age = " << age << endl;
}
~Person() {
cout << "析构函数被调用" << endl;
}
};
void testPerson() {
Person p2;
}
void main() {
testPerson(); //如果调用别的函数,别的函数中创建的对象,生命周期为该函数的生命周期;
Person p1; //如果在main() 函数中 创建对象的生命周期为程序生命周期。
system("pause");
}
构造函数的分类及其调用
两种分类方式:
- 按参数分类:有参构造,无参构造。
- 按类型分类:普通构造,拷贝构造。
拷贝构造函数 类名(const 类名& p){}
//const 别忘记了。
三种调用方法:
- 括号法
- 显示法
- 隐式转换法
注意事项
注意事项!!!!!!!!
- 括号法默认调用构造函数的时候不要加括号;
如:Person p4();
//这是错的!!
因为编译器会认为其声明了一个 p4() 的函数,返回类型为Person !!!!且编译器不会报错。 - 匿名构造函数,执行完毕后系统会立即回收 匿名对象。
- 不要用拷贝构造函数来初始化匿名对象。
如:Person(p3);
这里编译器会认为,Person(p3) 就是Person p3
编译器会以为创建 名为p3 的Person 对象,编译时报重定义的错,
相关笔记全在下方代码注释部分:
#include <iostream>
using namespace std;
//1.构造函数的分类及其调用
/*
按参数分类:
1.无参构造;(默认构造)
2.有参构造;
按类型分类:
1.普通构造;
2.拷贝构造;
*/
class Person {
public:
Person() { //无参构造函数
cout << "无参构造函数被调用" << endl;
}
Person(int a) { //有参构造函数
age = a;
cout << " 有参构造,传入的年龄为: " << age << endl;
}
Person(const Person& p) { //拷贝构造函数。
//将传入的人身上的所有属性,拷贝到我身上。
cout << " 拷贝构造函数被调用" << endl;
age = p.age;
cout << " 拷贝构造函数中 age = " << age <<endl;
}
int age;
~Person() {
cout << "析构函数被调用~~~喵~" << endl;
}
};
//调用
void test01() {
//1.括号法
//注意调用默认构造函数时候,不要加( )括号;
//因为下面这行代码,会被编译器认为是一个函数的声明;
// Person p4(); 函数声明,但是编译器不会报错。可以通过析构函数来证明其没有被创建。
Person p2(10);
Person p3(p2); //调用了拷贝构造函数
}
void test02() {
//2.显示法
Person p1;
Person p2 = Person(10); //有参构造
Person p3 = Person(p2); //拷贝构造
Person(101);//匿名对象,当前 行执行结束后,系统会立即回收掉匿名对象。
//注意:不要用拷贝构造函数,来初始化匿名对象
//Person(p3); //编译器会报 重定义错误。 因为 Person(p3) ==== Person p3 编译器以为它会创建对象。对象名重复。
cout << "aaaaaaaaaaa" << endl;
}
void test03() {
//3.隐式转换法
Person p4 = 10; //相当于 写了 Person p4 = Person(10); 有参构造函数。
Person p5 = p4; //隐式调用,拷贝构造函数。
}
void main() {
test03();
cout << "==============================" << endl;
}