C++拥有构造函数和析构函数,这两个函数将会被编译器自动调用,完成对象初始化和清理工作。对象的初始化和清理工作是编译器强制要我们做的事情,因此如果我们不提供构造和析构,编译器提供的构造函数和析构函数是空实现。
·构造函数:主要作用在于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无须手动调用。
·析构函数:主要作用在于对象销毁前系统自动调用,执行一些清理工作。
语法:
构造函数语法:类名(){}
1.构造函数,没有返回值也不写void
2.函数名称与类名相同
3.构造函数可以有参数,因此可以发生重载
4.程序在调用对象时候会自动调用构造,无须手动调用,而且只会调用一次
析构函数语法:~类名(){}
1.析构函数,没有返回值也不写void
2.函数名称与类名相同,在称前加上符号
3.析构函数不可以有参数,因此不可以发生重载
4.程序在对象销毁前会自动调用析构,
代码:
- #include
- using namespace std;
- class person {
- public:
- person() {
- cout << "person 构造函数调用" << endl;
- }
- ~person() {
- cout << "person 析构函数调用" << endl;
- }
-
- };
- void func() {
- person a;
- }
- int main() {
- func();
- return 0;
- }
两种分类方式:
按参数分为:有参构造和无参构造
按类型分为:普通构造和拷贝构造
三种调用方式:
括号法
显示法
隐式转换发
(1)有参和无参构造函数
代码:
- #include
- using namespace std;
- class person {
- public:
- person() {
- cout << "person 无参构造函数调用" << endl;
- }
- person(int a) {
- cout << "person 有参构造函数调用" << endl;
- }
- ~person() {
- cout << "person 析构函数调用" << endl;
- }
-
- };
- void func() {
- person a(1);
- }
- int main() {
- func();
- return 0;
- }
(2)普通和拷贝构造函数
代码:
- #include
- using namespace std;
- class person {
- public:
- int age;
- person() {
- cout << "person的普通构造函数" << endl;
- }
- person(const person& p) {
- age = p.age;
- //可以将传入的人的所有属性,拷贝到神上
- cout << "person的拷贝构造函数" << endl;
- }
- };
- void func() {
- //1.括号法
- person p1;
- p1.age = 10;
- person p2(p1);
- cout << p2.age << endl;
- }
- int main() {
- func();
- return 0;
- }
括号法
显示法
隐式转换发
(1)括号法:
- #include
- using namespace std;
- class person {
- public:
- int age;
- person() {
- cout << "person的普通构造函数" << endl;
- }
- person(int a) {
- age = a;
- cout << "person的普通构造函数" << endl;
- }
- person(const person& p) {
- age = p.age;
- //可以将传入的人的所有属性,拷贝到神上
- cout << "person的拷贝构造函数" << endl;
- }
- };
- void func() {
- //1.括号法
- person p1; //默认
- p1.age = 10;
- person p2(20); //有参
- person p3(p1); //拷贝
-
- //2.
- }
- int main() {
- func();
- return 0;
- }
注意: person p() 会被认为是函数声明,并不是调用默认构造
(2)显示法:
- #include
- using namespace std;
- class person {
- public:
- int age;
- person() {
- cout << "person的普通构造函数" << endl;
- }
- person(int a) {
- age = a;
- cout << "person的普通构造函数" << endl;
- }
- person(const person& p) {
- age = p.age;
- //可以将传入的人的所有属性,拷贝到神上
- cout << "person的拷贝构造函数" << endl;
- }
- };
- void func() {
- //2.显示法
- person p1; //默认
- p1.age = 10;
- person p2=person(20); //有参
- person p3=person(p1); //拷贝
-
- //2.
- }
- int main() {
- func();
- return 0;
- }
1.person(20)称为匿名对象,当前行执行后系统会立即回收匿名对象
2.不要用拷贝构造函数初始化匿名对象,person(p3) ->person p3;相当于重新定义一个p3,发生重定义错误。
(3) 隐式转换法:
- #include
- using namespace std;
- class person {
- public:
- int age;
- person() {
- cout << "person的普通构造函数" << endl;
- }
- person(int a) {
- age = a;
- cout << "person的普通构造函数" << endl;
- }
- person(const person& p) {
- age = p.age;
- //可以将传入的人的所有属性,拷贝到神上
- cout << "person的拷贝构造函数" << endl;
- }
- };
- void func() {
- //3.隐式转换发
- person p1; //默认
- person p2=10; //相当于person p2=person(10);
- person p3 = p2; //相当于person p3 = person(p2);
- }
- int main() {
- func();
- return 0;
- }
1.使用一个已经创建完毕的对象来初始化一个新对象。
2.值传递的方式给函数参数传值
3.以值方式返回局部对象
代码:
- #include
- using namespace std;
- class person {
- public:
- int a;
- int b;
- person() {
- cout << "person的无参构造函数" << endl;
- }
- person(int a1) {
- a = a1;
- cout << "person的有参构造函数" << endl;
- }
- person(const person &p) {
- a = p.a;
- cout << "person的拷贝构造函数" << endl;
- }
- ~person() {
- cout << "person的析构函数" << endl;
- }
- };
- void fun() {
- person A(10);
- person B(A);
- cout << B.a << ' ' << B.b << endl;
- }
- int main() {
- fun();
- return 0;
- }
作为函数值传递时,只会复制拷贝函数中已将定义要拷贝的变量,其余的即使已经外部定义了,只要拷贝函数中没有指明要拷贝,形参就不会拷贝。
- #include
- using namespace std;
- class person {
- public:
- int a;
- int b;
- int c;
- person() {
- cout << "person的无参构造函数" << endl;
- }
- person(int a1) {
- a = a1;
- cout << "person的有参构造函数" << endl;
- }
- person(const person &p) {
- a = p.a;
- cout << "person的拷贝构造函数" << endl;
- }
- ~person() {
- cout << "person的析构函数" << endl;
- }
- };
- void fun(person A) {
- cout << A.a << ' ' << A.b <<' '<
- }
- int main() {
- person A(10);
- A.b = 90;
- cout << A.a << ' ' << A.b << ' ' << A.c << endl;
- fun(A);
- return 0;
- }
1.3.3以值方式返回局部对象
同做做参数一样,也只复制拷贝函数中定义要复制的部分,并不是完全复制。
- #include
- using namespace std;
- class person {
- public:
- int a;
- int b;
- int c;
- person() {
- cout << "person的无参构造函数" << endl;
- }
- person(int a1) {
- a = a1;
- cout << "person的有参构造函数" << endl;
- }
- person(const person &p) {
- a = p.a;
- cout << "person的拷贝构造函数" << endl;
- }
- ~person() {
- cout << "person的析构函数" << endl;
- }
- };
- person fun() {
- person A(10);
- A.b = 90;//已经赋值,但是形参还是随机值
- cout << A.a << ' ' << A.b << ' ' << A.c << endl;
- return A;
-
- }
- int main() {
- person A=fun();
- cout << A.a << ' ' << A.b << ' ' << A.c << endl;
- return 0;
- }
1.4构造函数调用规则
默认情况下,c++编译器至少给一个类添加3个函数
1.默认构造函数(无参,函数体为空)
2.默认析构函数(无参,函数体为空)
3.默认拷贝构造函数,对属性进行值拷贝(全部)
构造函数调用规则如下:
1.如果用户定义有参构造函数,c+不在提供默认无参构造,但是会提供默认拷贝构造
2.如果用户定义拷贝构造函数,C++不会再提供其他构造函数
代码:
- #include
- using namespace std;
- class person {
- public:
- int a;
- int b;
- int c;
-
- person(int a1) {
- a = a1;
- cout << "person的有参构造函数" << endl;
- }
-
- ~person() {
- cout << "person的析构函数" << endl;
- }
- };
- person fun() {
- person A(10);
- A.b = 90;
- //person B; 报错
- return A;
-
- }
- int main() {
- fun();
- return 0;
- }
1.5深拷贝和浅拷贝
浅拷贝就是简单的赋值操作,深拷贝就是
代码:
- #include
- using namespace std;
- class person {
- public:
- int a;
- int* b;
- person(int a1, int b2) {
- a = a1;
- b = new int(b2);
- }
- person(const person &p) { //浅拷贝
- a = p.a;
- b = p.b;
- }
- ~person() { //浅拷贝
- if (b != NULL) {
- delete b;
- b = NULL;
- }
- }
- };
- void fun() {
- person a(10,90);
- person b(a);
- cout << b.a << ' ' << *b.b << endl;
- }
- int main() {
- fun();
- return 0;
- }
此时代码会报错,因为此时有两个析构函数,因此会是否两次相同地址的空间,此时要改为深拷贝。
代码:
- #include
- using namespace std;
- class person {
- public:
- int a;
- int* b;
- person(int a1, int b2) {
- a = a1;
- b = new int(b2);
- }
- person(const person &p) { //深拷贝
- a = p.a;
- b = new int(*(p.b));
- }
- ~person() {
- if (b != NULL) {
- delete b;
- b = NULL;
- }
- }
- };
- void fun() {
- person a(10,90);
- person b(a);
- cout << b.a << ' ' << *b.b << endl;
- }
- int main() {
- fun();
- return 0;
- }
1.6初始化列表
C++提供了初始化列表语法,用来初始化属性。
语法:构造函数() : 属性值1(值1),属性值2(值2)....... { }
代码:
- #include
- using namespace std;
- class person {
- public:
- int a;
- int b;
- int c;
- person(int a1,int b1,int c1) :a(a1), b(b1), c(c1) { //初始化列表
-
- }
- };
- void fun() {
- person p(30, 3,78);
- cout << p.a << ' ' << p.b << ' ' << p.c << endl;
- }
- int main() {
- fun();
- return 0;
- }