1、构造函数

一、什么是构造函数

c++中有一种特殊的成员函数,他的名字和类名相同,没有返回值,而在创建对象时会自动执行,类中的数据成员的初始化往往通过构造函数来实现。完成类中数据成员的初始化,同时也是类中的成员函数,但是比较特殊

二、如何给构造函数传参

有参构造,在定义对象是=时给出实参:类名 实例名(实参1,实参2,.....)

构造函数不需用户调用,也不能被用户调用,在创建对象时会被自动调用,但是在声明一个类的指针对象时,构造函数不会被调用,当new一个空间的时候,构造函数也会被调用。

如果用户自己没有定义构造函数,则C++系统会自动生成一个构造函数,只是这个构造函数的函数体是空的,也没有参数,不执行初始化操作。

在构造函数的函数体中不仅可以对数据成员赋初值,而且可以包含其他语句。但是一般不提倡在构造函数中加入与初始化无关的内容,以保持程序的清晰。

对于无参构造函数,在创建对象时,不可以写成:类名 对象名()

//构造函数的主要功能是完成类中数据成员的初始化,同时它也是类中的一个成员函数,但是比较特殊
class stu
{public:string name;int age;/* stu(string n,int a,int myid){cout << "构造函数" << endl;name = n;age = a;id = myid;}*/stu(){name = "temp";age = 0;id = 100;}void print()//根据有无形参,构造函数分为:有参构造函数 和无参构造函数{cout << name << age<<":"<<id  << endl;}private:int id;};int main()
{//传统的初始化成员的方式主要针对类中的公有数据成员是有效的,如果存在私有成员或受保护成员 则在类外初始化无法实现/* stu s1;s1.name = "sdfd";s1.age = 12;stu s2 = { "yyy",33 };s2.print();*/// -----------------------------------//构造函数不需要用户去显式调用,在创建类对象时,会自动调用该类的构造函数// stu s1("zhangsan",33,1001);//   stu s2;//创建对象时 如果该类的构造函数没有形参,则可以省略对象后的小括号。// s2.print();//temp0:100return 0;
}
class stu
{public:string name;int age;stu(string n,int a,int myid) //一个类中可以存在多个构造函数{cout << "构造函数" << endl;name = n;age = a;id = myid;// print();}stu()//在C++中,无参构造函数也称为默认构造函数,如果构造函数提供的形参全是默认形参类型,则该构造也属于默认构造函数{name = "temp";age = 0;id = 100;}void print()//根据有无形参,构造函数分为:有参构造函数 和无参构造函数{cout << name << age<<":"<<id  << endl;}private:int id;};int main()
{stu s1("zhangsan",33,1001);//构造函数的调用时机时在创建对象时,创建几个对象 就调用几次构造函数stu s2;//创建对象时 如果该类的构造函数没有形参,则可以省略对象后的小括号。s2.print();//temp0:100return 0;
}

int add(int num1,int num2)
{return num1 + num2;
}int sub(int num1, int num2)
{return num1 - num2;
}int mul(int num1, int num2)
{return num1 * num2;
}int   div1(int num1, int num2)
{return num1 / num2;
}int main()
{int num1, num2;cin >> num1 >> num2;cout<<   add(num1, num2)<<endl;cout << sub(num1, num2) << endl;cout << mul(num1, num2) << endl;cout << div1(num1, num2)<< endl;return 0;
}class cal
{
public:int num1;int num2;cal(int a, int b){num1 = a;num2 = b;}int add(){return num1 + num2;}int sub(){return num1 - num2;}int mul(){return num1 * num2;}int   div1(){return num1 / num2;}};int main()
{int num1, num2;cin >> num1 >> num2;//cout<<   add(num1, num2)<<endl;//cout << sub(num1, num2) << endl;//cout << mul(num1, num2) << endl;//cout << div1(num1, num2)<< endl;cal jsq(num1, num2);cout << jsq.add() << endl;cout << jsq.sub() << endl;cout << jsq.mul() << endl;cout << jsq.div1() << endl;return 0;
}

三、参数初始化列表

成员初始化表的一般形式为:

构造函数名(【参数表】):数据成员名1(初始值1),数据成员2(初始值2),,,,,,,,,,

{

         //构造函数体

}

1、执行带参数初始化列表的构造函数时,先执行初始化列表,后执行构造的函数体代码

2、初始化列表可以用于全部成员变量,也可以只用于部分成员变量

3、初始化的顺序和其在类中声明时的顺序是一致的,与列表的先后顺序无关

4、成员初始化列表只能用于构造函数

class stu
{
public:string name;int age;const int a;//常数据成员int& temp;//引用类型的数据成员   name("laoguo")  name="laoguo"//初始化列表中的成员的初始化顺序和书写顺序无关,和成员在类中的定义顺序有关stu(int kk):a(10),name("laoguo"),temp(kk) //当构造函数中的形参比较多时,用初始化列表可以提高程序的性能{age = 12;/*  name = "";age = 12;a = 1000;*/}void print(){cout << name << age << ":" << id << endl;}private:int id;};int main()
{stu s1(30);s1.print();return 0;
}
class date
{
public:int year;int month;int day;date(int y, int m, int d) //一旦类中用户提供了构造函数,系统不会在为该类自动生成{year = y;month = m;day = d;}/*date(){year = 0;month = 0;day = 0;}*/};class stu
{
public:string name;int age;date bir;//3.当用另一个类对象作为当前类的数据成员时,如果该类没有提供默认构造函数,此时需要通过初始化列表的方式来初始化该对象。stu(string n, int a, int y, int m, int d):bir(y,m,d){name = n;age = a;}};int main()
{return 0;
}

四、默认构造函数

2、拷贝构造函数

对类中的数据成员进行初始化

需要用到多个完全相同的对象,要将对象在某一个瞬间的状态保留下来,这就是对象的赋值机制,用一个已有的对象快速地复制处多个相同的对象,如Box1,Box2(Box1)去克隆处一个新对象Box2。

拷贝构造函数的本质是定义对象之间的规则,确定了那些成员需要拷贝,那些不需要拷贝

拷贝构造函数的一般格式:A(const A & a)

class stu
{
public:string name;int age;stu(string n,int a,int myid){name = n;age = a;id = myid;}stu() {}void print(){cout << name << age <<"#" << id << endl;}private:int id;};int main()
{stu s1("laogup", 23,1001);stu s2;//通过赋值运算符,可以将=右边对象的所有数据成员拷贝到=左边的对象中,用赋值实现拷贝是全拷贝。s2 = s1;//同类型的对象之间可以相互赋值,主要将一个对象中的数据成员值赋值给另外一个对象//如果在实现对象间拷贝的时候 你想有所选择的拷贝,需要通过拷贝构造函数s2.print();return 0;
}
class stu
{
public:string name;int age;string s_name;stu(string n,int a,string sname){cout << "普通构造函数" << endl;name = n;age = a;s_name = sname;}//拷贝构造函数 特点:只有一个形参并且该形参属于当前所在类的类类型,拷贝构造的形参不能采用值传递stu(const stu& temp){cout << "拷贝构造函数" << endl;//定义temp与当前对象之间的拷贝原则name = "";age = 0;s_name = temp.s_name;}stu() {}void print(){cout << name << age<<"#" << s_name << endl;}};int main()
{stu s1("laoguo", 23,"建大华清");// stu s2(s1);//实现了用s1对象来初始化s2对象  ,如果用户没有定义拷贝构造,系统会自动生成一个,并实现全拷贝stu s2 = s1;// stu s2(s1) 都匹配的是拷贝构造函数/* stu s2;s2 = s1;*/s2.print();//0#建大华清return 0;
}
class stu
{
public:string name;int age;string s_name;stu(string n,int a,string sname){cout << "普通构造函数" << endl;name = n;age = a;s_name = sname;}//拷贝构造函数 特点:只有一个形参并且该形参属于当前所在类的类类型,拷贝构造的形参不能采用值传递stu(const stu& temp){cout << "拷贝构造函数" << endl;//定义temp与当前对象之间的拷贝原则name = "";age = 0;s_name = temp.s_name;}stu() {}void print(){cout << name << age<<"#" << s_name << endl;}};void test(stu tt)
{}stu mytest()
{stu s2("ttt", 44, "sdf");return s2;//3 在函数中返回一个对象}int main()
{stu s1("laoguo", 23,"建大华清");test(s1);//2用一个对象做值传递// 1. stu s2(s1);mytest();return 0;
}

3、析构函数

析构函数是一个特殊的由用户定义的成员函数,当该类的对象离开了他的域(对象的生命周期结束时)或者delete表达式应用到一个该类的对象的指针上时,析构函数会自动被调用

析构函数的名字是在类名前加上波浪线~,他不返回任何值,也没有任何参数,我们可以为一个类定义多个构造函数,但是我们只能提供一个析构函数,他将应用于类的所有对象上。

主要功能是做清理和收尾

class stu
{
public:string name;int age;string s_name;stu(string n,int a,string sname){cout << "普通构造函数" << endl;name = n;age = a;s_name = sname;}stu() { cout << "默认构造函数" << endl; }void print(){cout << name << age<<"#" << s_name << endl;}//析构函数: ~类名(){}    不需要用户主动调用,当某个对象在离开它的域就会触发 该对象所属类中的析构函数~stu() //析构函数的作用:清理收尾工作{cout << "析构函数" << endl;}};void test()
{static stu s3;}int main()
{stu s1;test();cout << "#############" << endl;stu s2;return 0;
}

4、匿名对象

只存在于构造该对象的那行代码,离开构造对象的哪行代码后立即调用该对象

int main()
{//匿名对象的创建:类型(【实参列表】),他的生存周期只存在于改行代码stu();//类名 对象名(【实参列表】)cout<<"#######"<<endl;return 0;
}

 5、this关键字

class stu
{
public:string name;int age;string s_name;// const int *a        int * const astu(string name,int age,string s_name)//在C++中,一般来说 成员函数中都有一个隐形的形参叫this     this == stu * const this{cout << "inner:"<<this << endl;//this指向的是当前对象的指针,this只能在类的成员函数内使用,类外不可以使用this->name = name;//1.当成员函数中 局部变量与类中的数据成员出现重名 ,此时可以通过this关键字来加以区分 this->age = age;this->s_name = s_name;}void print(){cout << name <<this-> age<<"#" << s_name << endl;}stu mytest(){return *this;//2.  返回当前对象}};int main()
{stu s1("laoguo", 12, "建大");cout << "outer" << &s1<< endl;stu s2("laoguo1", 12, "建大");
//inner:00A0FAFC
//outer00A0FAFCreturn 0;
}

6、对象的动态建立和释放

如果我们希望在需要用到对象时才建立对象,在不需要用该对象时就撤销它,释放它所占的内存空间以供别的数据使用,除了沿用C语言提供的malloc与free函数外,还可以:

在c++利用new操作符在堆区开辟数据空间,手动开辟就需要手动释放,释放时利用delete操作符。

一、new运算符

作用:分配内存(堆上),调用构造函数

一般格式:new 类型(初值单值)

                  new 类型 {初值多值}

                   new类型【大小】;

二、delete运算符

例子:


class stu
{
public:string name;int age;string s_name;stu(string name,int age,string s_name){cout << "inner:"<<this << endl;this->name = name;this->age = age;this->s_name = s_name;}void print(){cout << name <<this-> age<<"#" << s_name << endl;}~stu(){cout << "析构函数" << endl;}};int main()
{//在堆上创建单对象和释放单个对象的案例int *pt= new int;//在堆上构建一个int大小的内存并返回给内存的首地址*pt = 1000;//对堆对象进行写操作cout << *pt << endl;//进行读操作int* pt1 = new int(10);//在堆上创建一个int对象 同时将其初始化为10cout << *pt1 << endl;stu* pp = new stu("laoguo",22,"北大");//在堆上构建一个类类型对象stucout << pp->name << endl;pp->print();//new和delete要成对出现delete pp;//当对一个堆对象施加delete 也会触发该类的析构函数return 0;
}
class stu
{
public:string name;int age;string s_name;stu(string name,int age){cout << "inner:"<<this << endl;this->name = name;this->age = age;}void print(){cout << name <<this-> age<< endl;}~stu(){cout << "析构函数" << endl;}};//批量在堆上构建对象的案例
int main()
{//  int* pt = new int[10]; //在堆上构建一个可以容纳10个整数类型的数组;//int* pt = new int[10]{ 11, 22, 33, 1, 2, 3, 4, 5, 6, 7 };//构建动态数组的同时并完成其整体的初始化//for (int i = 0; i < 10; i++)//{//    cout << pt[i] << endl;//}stu* pp = new stu[3]{ {"kk",3},{"pp",5},{"yy",7}};for (int i = 0; i < 3; i++){cout << pp[i].name << pp[i].age << endl;}delete[] pp;return 0;
}

7、共用数据的保护(const)

一、常对象

格式:const <类名> <对象名>;

<类名> const <对象名>;

//常对象的 案例class stu
{
public:string name;int age;stu(string name,int age){cout << "inner:"<<this << endl;this->name = name;this->age = age;}void test(string ljs){name = ljs;}void print(){cout << name <<this-> age<< endl;}~stu(){cout << "析构函数" << endl;}};int main()
{//通过常对象,可以访问类中的数据成员,但是不可以对其做修改。一旦定义了常对象 相当于对类中的所有数据成员都加了const 约束const stu s1("laoguo", 22);//定义一个stu类型的常对象cout << s1.name << endl;//s1.test(); 常对象不可以调用类中的非 常成员函数//  s1.name = "laozhang"; 是错的return 0;
}

二、常数据成员

//常数据成员的使用案例
class stu
{
public:string name;int age;const int score;//常数据成员,不要试图对常数据成员中的值进行修改,但是可以读stu(string name,int age,int sc):score(sc)//对与常数据成员需要通过初始化列表来对其初始化{cout << "inner:"<<this << endl;this->name = name;this->age = age;}void print(){cout << name <<this-> age<<score<< endl;}~stu(){cout << "析构函数" << endl;}};int main()
{stu s1("laozhang", 12, 80);return 0;
}

三、常成员函数

//常成员函数 使用案例class stu
{
public:string name;int age;const int score;//常数据成员,不要试图对常数据成员中的值进行修改,但是可以读stu(string name,int age,int sc):score(sc)//对与常数据成员需要通过初始化列表来对其初始化{cout << "inner:"<<this << endl;this->name = name;this->age = age;}//常成员函数void mytest()const{cout << age << endl;cout << "加const的函数";//  age = 33;//在常 成员函数眼中,类中的任何数据成员都是神圣不可侵犯(只能读不可以改)//print();是错的,在常成员函数中 不可以调用类中非 常成员函数}//void mytest()//在类中 重载时 有一个特殊的情况,就是函数后加const 和不加const 可以重载成功//{//    cout << "不加const的函数";////}void print(){cout << name <<this-> age<<score<< endl;//age = 33;mytest();//类中的非 常成员函数可以调用类中的常成员函数}~stu(){cout << "析构函数" << endl;}};int main()
{stu s1("laozhang", 12, 80);s1.mytest();const stu s2("sdf", 33, 55);//常对象可以调用类中常成员函数s2.mytest();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/86493.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/86493.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/86493.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

带标签的 Docker 镜像打包为 tar 文件

现在还有人用docker吗 要将带标签的 Docker 镜像打包为 tar 文件&#xff0c;请使用 docker save 命令。以下是详细操作指南&#xff1a; 一、单镜像打包&#xff08;推荐方式&#xff09; # 基础格式 docker save -o [输出文件名].tar [镜像名]:[标签]# 示例&#xff1a;将…

基于GPS-RTK的履带吊车跑偏检测技术方案

基于GPS-RTK的履带吊车跑偏检测技术方案 1. 引言 1.1 项目背景 履带吊车作为重型工程机械&#xff0c;其行驶稳定性直接关系到作业安全和设备寿命。跑偏现象会导致履带异常磨损、转向系统过载&#xff0c;严重时可能引发侧翻事故。传统检测方法&#xff08;如激光测距或人工观…

勾正数据大数据开发面试题整理-20250625

最近面了家公司&#xff0c;想看看自己多年不准备面试&#xff0c;靠着老本能面试成啥样&#xff0c;算是试试水吧&#xff0c;一面过了&#xff0c;二面有个算法题没答出来&#xff0c;整体答得状态也不太好&#xff0c;应该是没过。 一面 先来说说一面吧&#xff0c;一面是…

基于中国香港会计准则差异,中国企业在香港推广ERP(SAP、Oracle)系统需要注意的细节

核心在于&#xff1a;ERP通常按单一会计准则设计主数据架构&#xff0c;但跨国企业需要同时满足两地报表要求。 用户常见的场景包括&#xff1a; 1 科目体系能否同时承载CAS的专项储备和HKFRS的禁止计提&#xff1f; 2 资产模块如何兼容不同的减值转回规则&#xff1f; 3 关联…

【编译原理】期末复习知识总结

目录 题型 总结 编译五大组成部分 编译与解释方式区别&#xff1f; 前端&#xff0c;后端&#xff0c;Why&#xff1f; 概念 推导、归约 短语、简单短语、句柄 文法 分类 正则文法&#xff08;3型&#xff09; NFA、DFA、最小化 自上而下语法分析&#xff08;推导…

【软考高级系统架构论文】论微服务架构及其应用

论文真题 论微服务架构及其应用近年来,随着互联网行业的迅猛发展,公司或组织业务的不断扩张,需求的快速变化以及用户量的不断增加,传统的单块(Monolithic) 软件架构面临着越来越多的挑战,已逐渐无法适应互联网时代对软件的要求。在这一背景下,微服务架构模式(Microservi…

【人工智能】RAG分块

在RAG&#xff08;检索增强生成&#xff09;系统中&#xff0c;文档分块&#xff08;Chunking&#xff09;是决定系统性能的核心环节&#xff0c;直接影响检索精度和生成质量。分块需平衡语义完整性、检索效率和上下文保留三大目标。 一、分块的核心标准 1.1 分块基础知识​ …

能耗管理新革命:物联网实现能源高效利用

在全球能源危机与 “双碳” 目标的双重压力下&#xff0c;企业与社会对能耗管理的重视程度达到前所未有的高度。然而&#xff0c;传统能耗管理方式存在数据采集滞后、分析维度单一、节能措施粗放等问题&#xff0c;无法满足精细化管理需求。物联网技术凭借其强大的数据感知、传…

基于CMS的黄道吉日万年历源码(自适应)

本模板采用帝国cms7.5版UTF-8制作&#xff1b; 适用站点&#xff1a;时间查询、时差计算、万年历、黄道吉日查询、假期查询、节气表等&#xff1b; 源码优势&#xff1a;代码精简&#xff0c;利于SEO、UI大气精简&#xff0c;搜索引擎收录高&#xff1b; 全站伪静态无需刷新生成…

如何构建个人AIagent

构建个人AI Agent是一个结合技术实现和场景设计的系统工程&#xff0c;以下是分步骤的详细指南&#xff0c;涵盖从需求定义到部署落地的全流程&#xff1a; ​一、明确Agent定位&#xff08;关键第一步&#xff09;​​ ​角色定义矩阵​ 类型典型场景技术复杂度示例信息处理Ag…

lutris登录不进去

日志 Cannot create Vulkan instance.This problem is often caused by a faulty installation of the Vulkan driver or attempting to use a GPU thatdoes not support Vulkan.ERROR at /home/abuild/rpmbuild/BUILD/vulkan-tools-1.4.313-build/Vulkan-Tools-vulkan-sdk-1.…

缓存与加速技术实践-NoSQL之Redis配置与优化

目录 #1.1关系数据库与非关系型数据库 1.1.1关心型数据库 1.1.2非关系型数据库 1.1.3非关系型数据库产生背景 #2.1redis简介 2.1.1redis安装部署 2.1.2配置参数 #3.1redis命令工具 3.1.1redis-cli命令行工具 3.1.2redis-benchmark测试工具 #4.1redis数据库常用命令 4.1.1ke…

走近科学IT版:FreeBSD系统下ThinkPad键盘突然按不出b、n、/和空格键了!

走近科学IT版&#xff1a;FreeBSD系统下ThinkPad键盘突然按不出b和n键了&#xff01; 很慌&#xff0c;以为键盘坏了&#xff0c;在控制台无法按出b和n&#xff0c;但是在浏览器里&#xff0c;可以按出来。 重启机器&#xff0c;结果在浏览器里也按不出来了.... 按Ctrl空格&a…

聚铭网络入选嘶吼《中国网络安全细分领域产品名录》“云平台安全管理”与“态势感知”双领域TOP10

近日&#xff0c;在嘶吼安全产业研究院发布的《中国网络安全细分领域产品名录》中&#xff0c;聚铭网络凭借其核心产品——聚铭云端安全管家与聚铭安全态势感知与管控系统&#xff0c;分别入选“云平台安全管理”与“态势感知”两大关键细分领域TOP10榜单&#xff0c;充分展现了…

DEYOLO 全面复现,将双增强跨模态目标检测网络 DEYOLO 融合到 YOLOFuse 框架

模型架构模态精度 P召回率 RmAP50mAP50-95模型大小(MB)计算量(GFLOPs)yolov8n (baseline)RGB0.8880.8290.8910.5006.28.1yolo-fuse-中期特征融合RGBIR0.9510.8810.9470.6012.613.2yolo-fuse-早期特征融合RGBIR0.9500.8960.9550.6235.26.7yolo-fuse-决策级融合RGBIR0.9560.9050.…

python基于Django+mysql实现的图书管理系统【完整源码+数据库】

摘要 随着信息技术与教育现代化的深度融合&#xff0c;图书管理系统的智能化与自动化成为提升资源利用效率的关键需求。本文基于Python语言&#xff0c;采用Django框架与MySQL数据库设计并实现了一套功能完备的图书管理系统&#xff0c;旨在通过信息化手段优化图书借阅流程、强…

论软件设计方法及其应用

20250427-作 题目 软件设计&#xff08;Software Design&#xff0c;SD)根据软件需求规格说明书设计软件系统的整体结构、划分功能模块、确定每个模块的实现算法以及程序流程等&#xff0c;形成软件的具体设计方案。软件设计把许多事物和问题按不同的层次和角度进行抽象&…

QT 自定义ComboBox,实现下拉框文本颜色设置

最近在做项目中遇到需求&#xff0c;在下拉框中&#xff0c;文本需要设置不同的颜色&#xff0c;遂网上了解了一番后&#xff0c;得出以下代码&#xff0c;可以完美实现效果&#xff0c;现分享出来&#xff01; 1.实现效果 2.自定义类 colorcombobox.h #ifndef COLORCOMBOBOX…

【时间戳】

在编程竞赛和高效数据处理场景中&#xff0c;时间戳技巧是一种极其高效的标记方法&#xff0c;常用于避免频繁清空数组或 map&#xff0c;提高算法运行效率。本文将从定义、应用场景、模板代码、技巧细节等方面系统整理时间戳的使用方式。 一、时间戳技巧是什么&#xff1f; 时…

json.decoder.JSONDecodeError: Unexpected UTF-8 BOM (decode using utf-8-sig)

有一次爬虫遇到了json的字符串响应对象 然后转为json对象 报这个错误 raise JSONDecodeError("Unexpected UTF-8 BOM (decode using utf-8-sig)", json.decoder.JSONDecodeError: Unexpected UTF-8 BOM (decode using utf-8-sig): line 1 column 1 (char 0) 意思是叫…