C++:构造函数以及析构函数
构造函数以及析构函数
- 对象初始化和清理
- 构造函数以及析构函数
- 构造函数的分类
- 括号法
- 显示法
- 隐式转换法
- 匿名对象
- 拷贝构造函数的调用时机
- 构造函数的调用规则
- 深拷贝和浅拷贝
- 初始化列表
- 类对象作为类成员
- 静态成员
对象初始化和清理
C++面向对象来源于生活,每个对象都会有初始化设置以及对象销毁前的清理数据的设置
构造函数以及析构函数
对象的初始化和清理是非常重要的安全问题
- 一个对象或者变量没有初始化状态,对其使用后果也是未知
- 使用完一个对象或者变量,没有及时清理,也会造成一定的安全问题
构造函数主要用于创造对象时为对象的成员属性赋值,构造函数由编译器自动调用,无需手动调用
析构函数主要用于销毁前系统自动调用,执行一些清理工作
构造函数语法:类名()
- 构造函数 没有返回值 也不写void
- 函数名称和类名相同
- 构造函数可以有参数,因此可以发生重载
- 程序在调用对象时自动调用构造函数,无需手动调用,且只会调用一次
析构函数语法:~类名()
- 析构函数,没有返回值也不写void
- 函数名称是在类名前加~
- 析构函数不可以有参数 因此不能发生重载
- 程序在对象销毁时自动调用析构函数,无需手动调用,且只会调用一次
#include <iostream>
#include <ctime>
#include <string>//c++中字符串需要添加这个头文件
#include <fstream>
using namespace std;class student
{public:student();~student();
};
student::student(){cout << "构造函数" << endl;
}
student::~student() {cout << "析构函数" << endl;
}
int main()
{ student stu;system("pause");return 0;
}
构造函数的分类
两种分类方式:
- 按参数:有参构造和无参构造
- 按类型:普通构造和拷贝构造
三种调用方式:
- 括号法
- 显示法
- 隐式转换法
调用默认构造的时候不要写括号()系统会默认成是函数的
不要利用拷贝构造函数初始化匿名对象 编译器会认为 类名(p3) ==person p3
括号法
#include <iostream>
#include <ctime>
#include <string>//c++中字符串需要添加这个头文件
#include <fstream>
using namespace std;class student
{public:student();//无参构造student(int age);//有参构造student(const student&b);//拷贝构造~student();
};
student::student()
{cout << "无参构造" << endl;
}
student::student(int age)
{cout << "有参构造" << endl;
}
student::student(const student&b)
{cout << "拷贝构造" << endl;
}
student::~student()
{cout << "析构函数" << endl;
}int main()
{ /*括号法*/student stu1;student stu2(18);student stu3(stu2);system("pause");return 0;
}
显示法
#include <iostream>
#include <ctime>
#include <string>//c++中字符串需要添加这个头文件
#include <fstream>
using namespace std;class student
{public:student();//无参构造student(int age);//有参构造student(const student&b);//拷贝构造~student();
};
student::student()
{cout << "无参构造" << endl;
}
student::student(int age)
{cout << "有参构造" << endl;
}
student::student(const student&b)
{cout << "拷贝构造" << endl;
}
student::~student()
{cout << "析构函数" << endl;
}int main()
{ /*显示法*/student stu1;student stu2 = student(18);student stu3 = student(stu2);system("pause");return 0;
}
隐式转换法
#include <iostream>
#include <ctime>
#include <string>//c++中字符串需要添加这个头文件
#include <fstream>
using namespace std;class student
{public:student();//无参构造student(int age);//有参构造student(const student&b);//拷贝构造~student();
};
student::student()
{cout << "无参构造" << endl;
}
student::student(int age)
{cout << "有参构造" << endl;
}
student::student(const student&b)
{cout << "拷贝构造" << endl;
}
student::~student()
{cout << "析构函数" << endl;
}int main()
{ /*隐式转换法*/student stu1;student stu2 = 10;student stu3 = stu2;system("pause");return 0;
}
匿名对象
匿名对象的意思就是当执行结束后系统立马收回
#include <iostream>
#include <ctime>
#include <string>//c++中字符串需要添加这个头文件
#include <fstream>
using namespace std;class student
{public:student();//无参构造student(int age);//有参构造student(const student&b);//拷贝构造~student();
};
student::student()
{cout << "无参构造" << endl;
}
student::student(int age)
{cout << "有参构造" << endl;
}
student::student(const student&b)
{cout << "拷贝构造" << endl;
}
student::~student()
{cout << "析构函数" << endl;
}int main()
{ /*匿名对象*/student(1);system("pause");return 0;
}
拷贝构造函数的调用时机
调用时机
- 使用一个已经穿件完毕的对象来初始化一个新的对象
- 以值传递的方式给函数参数传值
- 以值方式返回局部对象
#include <iostream>
#include <ctime>
#include <string>//c++中字符串需要添加这个头文件
#include <fstream>
using namespace std;class student
{public:student();//无参构造student(int age);//有参构造student(const student&b);//拷贝构造~student();
};
student::student()
{cout << "无参构造" << endl;
}
student::student(int age)
{cout << "有参构造" << endl;
}
student::student(const student&b)
{cout << "拷贝构造" << endl;
}
student::~student()
{cout << "析构函数" << endl;
}void test1(student stu)
{}
student test2()
{student stu;cout << &stu << endl;return stu;
}
int main()
{ /*使用一个已经创建完毕的对象来初始化一个新对象*/student stu(18);student stu1(stu);/*以值传递的方式给函数传递值*/test1(stu);/*以值的方式返回局部对象*/student stu2 = test2();cout << &stu2 << endl;system("pause");return 0;
}
上面的代码输出的地址也表示了 拷贝构造函数是拷贝一个新的构造函数,所以地址会不同
构造函数的调用规则
默认情况下,c++编译器至少给1个类添加3个函数
- 默认构造函数(无参,函数体为空)
- 默认析构函数(无参,函数体为空)
- 默认拷贝构造函数,对属性进行值拷贝
构造函数调用规则:
- 如果用户定义有参构造函数,c++不提供默认无参构造函数,但依然会提供默认拷贝构造
- 如果用户定义拷贝构造函数,c++不会再提供其他构造函数
下面几张截图就可以充分说明上述构造函数调用规则:
1. 只定义有参构造,声明无参构造会报错 声明拷贝构造不会报错
2. 只定义拷贝构造,声明无参构造和有参构造都会报错
3. 定义了无参构造和有参构造,声明拷贝构造不会报错
深拷贝和浅拷贝
浅拷贝:简单的赋值拷贝操作
深拷贝:在堆区重新申请空间,进行拷贝操作
先把代码放上来,然后说一下区别
#include <iostream>
#include <ctime>
#include <string>//c++中字符串需要添加这个头文件
#include <fstream>
using namespace std;class student
{public:int age;int *hight;student();//无参构造student(int xage,int xhight);//有参构造student(const student&b);//拷贝构造~student();
};
student::student()
{cout << "无参构造" << endl;
}
student::student(int xage, int xhight)
{age = xage;hight = new int(xhight);cout << "有参构造" << endl;
}
student::student(const student&b)
{cout << "拷贝构造" << endl;age = b.age;hight = b.hight;//浅拷贝hight = new int(*b.hight);//深拷贝
}
student::~student()
{if (hight != NULL){delete hight;hight = NULL;}cout << "析构函数" << endl;
}int main()
{ student stu(18, 180);cout << stu.age << endl;cout << stu.hight << endl;student stu1(stu);cout << stu1.age << endl;cout << stu1.hight << endl;system("pause");return 0;
}
上面代码不可直接使用,在深拷贝和浅拷贝哪里应该要注释一个,现在我来贴出不同情况下运行后的结果
浅拷贝
深拷贝
首先肯定的是,这个代码在浅拷贝的时候运行出错了。首先我们可以看到,拷贝之后的heigh的地址指向的是一样。那么在程序结束的时候,析构函数会delete这个指针,但是由于浅拷贝中hight中2个函数指向的地址一样,所以析构函数相当于delete一个相同的指针2次,那么必然会出错的。
深拷贝是自己在堆区重新开辟的一个新的空间,自然而然2个hight指向的地址不是一个,这个我们打印的结果也看到了,所以在析构函数释放的时候自然不会报错
初始化列表
前面我们写的代码中有参构造,都是在函数内部实现属性和形参的赋值
这个初始化列表作用就是C++提供了初始化列表语法,用来初始化属性
语法:槽函数():属性1(值1)属性2(值2)
传统方式
#include <iostream>
#include <ctime>
#include <string>//c++中字符串需要添加这个头文件
#include <fstream>
using namespace std;class student
{public:int a, b, c;student(int xa,int xb,int xc);//有参构造//student(int xa, int xb, int xc) :a(xa), b(xb), c(xc)//{}~student();
};student::student(int xa, int xb, int xc)
{a = xa;b = xb;c = xc;cout << "有参构造" << endl;
}student::~student()
{cout << "析构函数" << endl;
}int main()
{ student stu(1, 2, 3);cout << stu.a << endl;cout << stu.b << endl;cout << stu.c << endl;system("pause");return 0;
}
初始化列表
#include <iostream>
#include <ctime>
#include <string>//c++中字符串需要添加这个头文件
#include <fstream>
using namespace std;class student
{public:int a, b, c;//student(int xa,int xb,int xc);//有参构造student(int xa, int xb, int xc) :a(xa), b(xb), c(xc){}~student();
};//student::student(int xa, int xb, int xc)
//{// a = xa;
// b = xb;
// c = xc;
// cout << "有参构造" << endl;
//}student::~student()
{cout << "析构函数" << endl;
}int main()
{ student stu(1, 2, 3);cout << stu.a << endl;cout << stu.b << endl;cout << stu.c << endl;system("pause");return 0;
}
类对象作为类成员
C++中类的成员可以是另外一个类,我们称改成员为对象成员
当其他类对象作为本类成员,构造时候要先构造对象,在构造自身
析构函数刚好相反
#include <iostream>
#include <ctime>
#include <string>//c++中字符串需要添加这个头文件
#include <fstream>
using namespace std;class phone
{public:string phonename;phone(string a){phonename = a;cout << "phone 的构造函数" << endl;}~phone(){cout << "phone 的析构函数" << endl;}
};
class student
{public:string name;phone phones;student(string xname, string xphone):name(xname),phones(xphone){cout << "student 的构造函数" << endl;}~student(){cout << "student 的析构函数" << endl;}
};int main()
{ student stu("张三","华为");system("pause");return 0;
}
静态成员
静态成员就是在成员变量和成员函数前加关键字static
静态成员变量
- 所有对象共享一份数据
- 在编译阶段分配内存
#include <iostream>
#include <ctime>
#include <string>//c++中字符串需要添加这个头文件
#include <fstream>
using namespace std;class student
{public:static int age;
};
int student::age = 18;int main()
{ student stu1;cout << stu1.age << endl;student stu2;stu2.age = 20;cout << stu1.age << endl;cout << &stu1.age << endl;cout << &stu2.age << endl;system("pause");return 0;
}
访问方式:
- 通过对象访问
- 通过类名访问
- 静态成员访问权限私有情况下也访问不到
类内声明,类外初始化
- 静态成员函数
- 所有对象共用一个函数
- 静态成员函数只能访问静态成员变量
- 静态成员函数权限是私有的也无法访问到
#include <iostream>
#include <ctime>
#include <string>//c++中字符串需要添加这个头文件
#include <fstream>
using namespace std;class student
{public:static int age;static void fun1(){age = 200;}
private:static void fun2(){}
};
int student::age = 18;int main()
{ student stu1;cout << stu1.age << endl;student::fun1();cout << stu1.age << endl;system("pause");return 0;
}
C++:构造函数以及析构函数相关推荐
- C++ 笔记(17)— 类和对象(构造函数、析构函数、拷贝构造函数)
1. 构造函数 构造函数是一种特殊的函数(方法),在根据类创建对象时被调用.构造函数是一种随着对象创建而自动被调用的函数,它的主要用途是为对象作初始化. 构造函数的名称与类的名称是完全相同的,并且不会 ...
- php构造和析构方法,php5构造函数与析构函数实例
自php5起,有了构造函数与析构函数. 这使得php更富有面向对象的魅力了. 在php4时,构造函数用的是与类同名的函数来进行构造这个动作. 例如: 复制代码 代码示例: /* * myclass.p ...
- 提高C++性能的编程技术笔记:构造函数和析构函数+测试代码
对象的创建和销毁往往会造成性能的损失.在继承层次中,对象的创建将引起其先辈的创建.对象的销毁也是如此.其次,对象相关的开销与对象本身的派生链的长度和复杂性相关.所创建的对象(以及其后销毁的对象)的数量 ...
- c++, 派生类的构造函数和析构函数 , [ 以及operator=不能被继承 or Not的探讨]
说明:文章中关于operator=实现的示例,从语法上是对的,但逻辑和习惯上都是错误的. 参见另一篇专门探究operator=的文章:<c++,operator=>http://www.c ...
- C++中的构造函数VS析构函数
1.构造函数 类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行.构造函数的名称与类的名称的完全相同的,并且不会返回任何数据类型,也不会返回void.构造函数用于为某些成员变量设置初 ...
- 多继承的构造函数和析构函数
//程序2:多继承的构造函数 与 析构函数 #include<iostream> using namespace std;class A { public: A() { cout<& ...
- c++ 构造函数析构函数 数据安全_C++知识点 16:构造函数和析构函数的语法
#define _CRT_SECURE_NO_WARNINGS #include using namespace std;// 创建一个类( 类内包括: 2个构造函数,一个析构函数) class Pe ...
- 多重继承的构造函数和析构函数
多重继承的构造函数和析构函数的执行顺序: //此处不做注释和说明了,看程序能读懂的 #include <iostream> using namespace std; class base1 ...
- C++中构造函数和析构函数
[注]致力于将知识讲明白!不懂请留言! 构造函数 定义 它是一种特殊的方法.主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中. 另外,一个类可以有 ...
- c++ map 析构函数_C++学习刷题6--C++类的使用:构造函数、析构函数和类的使用
一.前言 本部分为C++语言刷题系列中的第4节,主要讲解这几个知识点:构造函数.析构函数和类的使用.欢迎大家提出意见.指出错误或提供更好的题目! 二.知识点讲解 由以前知识可知,类的实现中包含成员变量 ...
最新文章
- mysql 用命令行复制表数据到新表
- 消费消息删除_【进阶之路】可靠消息最终一致性解决方案
- 第4章 Python 数字图像处理(DIP) - 频率域滤波7 - 二维DFT和IDFT的一些性质 - 傅里叶频谱和相角
- java与php链条遇到的坑,记一次Java加密加签算法到php的坑
- JS:ES6-2 const 关键字
- idea 2019最新版无法打开报错问题,Error occurred during initialization of VM Initial heap size set to a larger va
- SAS9.4安装简易教程(保姆级)附带报错处理
- ctfmon是什么启动项_Win7启动项找不到ctfmon进程无法正常使用输入法的解决方法...
- 双系统如何卸载linux
- 值得收藏-50个免费可商用图库
- 诗词大全给力版_小学生诗词必背75+80首,课内课外全掌握,还送配套练习册amp;视频课...
- 华为OD(外包)社招技术二面,总结复盘
- 无插件播放之http-flv
- python显示gif图片报错_4种方法(plglet、tkinter、guizero、pygame)的GUI中显示gif
- Unity中的特殊的文件夹
- 云之讯张雯:云计算时代融合通讯开发及算法优化
- 记录12款MacBook Pro MC946,A1398拆主板换新喇叭的过程
- 机器学习算法工程师面试学习经验
- 记一次godaddy上同一共享主机上部署多站
- Android onMeasure、Measure、measureChild、measureChildren 一些简要说明