1.对象的初始化(构造函数)和清理(析构函数)
(1)构造函数:主要作用用于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用。
(2)析构函数:主要作用在于对对象销毁前系统自动调用,执行一些清理工作。
注意:对象的初始化和清理工作是编译器强制我们要做的事情,因此如果我们不提供这两个函数,编译器会提供编译器的这两个函数是空实现。
2.这两个函数的用法
(1)构造函数语法:类名(){}
a.构造函数没有返回值也不写void
b.函数名与类名相同
c.构造函数可以有参数,因此可以发生重载
d.程序在调用对象时会自动调用构造,无需手动调用,而且只调用一次
(2)析构函数语法:~类名(){}
a.析构函数没有返回值也不写void
b.函数名与类名相同,在函数名前加~
c.构造函数不可以有参数,因此不可以发生重载
d.程序在调用对象时会自动调用析构,无需手动调用,而且只调用一次
#include <iostream> using namespace std; class Person { public: //1.构造函数,进行初始化操作 Person() { cout << "Person构造函数的调用" << endl; } //2.析构函数,进行清理操作 ~Person() { cout << "Person析构函数的调用" << endl; } }; void test01() { Person p;//在栈上的数据,test01执行完毕后,释放这个函数 } int main() { test01(); Person p;//这里不会执行析构函数,只有在main函数执行完毕再回执行析构函数 system("pause"); return 0; }
3.构造函数的分类及调用
(1)两种分类:按参数分为(有参构造和无参构造),按类型分类(普通构造和拷贝构造)
(2)调用方式:括号法、显示法、隐式转换法
#include<iostream> using namespace std; class Person { public: //无参(默认)构造函数 Person() { cout << "Person无参构造函数的调用" << endl; } //有参构造函数 Person(int a) { age = a; cout << "Person有参构造函数的调用" << endl; } //拷贝构造函数 Person(const Person &p) { //将传入的这个人的所有属性,拷贝到当前对象函数 age = p.age; cout << "Person拷贝构造函数的调用" << endl; } //析构函数 ~Person() { cout << "Person析构函数的调用" << endl; } public: int age; }; //调用 void test01() { //括号法 //注意事项1:调用默认构造函数时不要加(),加了括号编译器可能会将它默认为函数声明 /*Person p1; Person p2(10); Person p3(p2); cout << "p2的年龄为:" << p2.age << endl;//10 cout << "p3的年龄为:" << p3.age << endl;//10*/ //显示法 //Person p1; Person p2 = Person(10);//单独的Person(10)是一个匿名对象p2是给他命一个名 cout << "aaaa" << endl;//这句话在有参构造函数调用后执行,然后在调用析构函数 //Person p3 = Person(p2); //Person(10);//特点:当前行执行结束后,系统给会立即回收掉匿名对象 //cout << "aaa" << endl;//这句话会在匿名对象被回收后才打印 //注意事项2:不要利用拷贝构造函数,初始化匿名对象 //Person(p2);//编译器会认为Person(p2) == Person p2,重复定义了 //隐式转换法 Person p4 = 10;//编译器默认为Person p4 = Person(10); Person p5 = p4; } int main() { test01(); system("pause"); return 0; }
4.拷贝构造函数的调用时机
使用以下3种方式都会调用拷贝构造函数
#include <iostream> using namespace std; class Person { public : Person() { cout << "Person默认构造函数调用" << endl; } Person(int age) { cout << "Person有参构造函数调用" << endl; m_age = age; } Person(const Person &p) { cout << "Person拷贝构造函数调用" << endl; m_age = p.m_age; } ~Person() { cout << "Person析构函数调用" << endl; } public: int m_age; }; //1.使用一个已经创建完毕的对象来初始化一个对象 void test01() { Person p1(20); Person p2(p1); cout << "p2的年龄为:" << p2.m_age << endl; } //2.值传递的方式给函数参数传值 void dowork(Person p) { } void test02() { Person p; dowork(p); } //3.值传递返回局部对象 Person dowork2() { Person p1; cout << (int *)&p1 << endl; return p1; } void test03() { Person p = dowork2(); cout << (int *)&p << endl; } int main() { //test01(); //test02(); test03(); system("pause"); return 0; }
5.构造函数调用规则
(1)在创建对象时C++编译器默认会提供三种构造函数
(2)如果用户定义有参构造函数,C++编译器不会在提供默认无参构造,但是会提供默认拷贝构造
(3)如果用户定义拷贝构造函数,c++编译器不会在提供其他构造函数(此时不能调用前两种构造函数)