C++面向对象程序设计 - 构造函数

        C++提供了构造函数来处理对象的初始化,构造函数是一种特殊的成员函数,与其他成员函数不同,它不需要用户来调用,而是在建立对象时自动执行。构造函数名称必须与类同名,而不能由用户任意命名,以便编译系统能识别它把它作为构造函数处理。它不具体任何类型,也不返回任何值。构造函数的功能由用户定义,可根据初始化的要求设计函数体和函数参数。而且如果用户未定义构造函数,C++系统会自动生成一个构造函数,只是这个构造函数体是空的。

        

一、默认构造函数

        用户未定义构造函数系统会自动生成一个构造函数,这个构造函数的函数体是空的,也没有参数,不执行初始化操作。代码如下:

#include <iostream>
#include <string>
using namespace std;class Student{private:int age;string name;string sex;public:void display(){cout <<"name:" <<name <<", age:" <<age <<", sex:" <<sex <<endl;}
};int main(){Student s;s.display();return 0;
}

执行效果如下:

二、自定义构造函数

        构造函数没有返回值,也不需要在定义构造函数时声明类型。构造函数是在建立对象时由系统自动执行的,而且只执行一次。这里创建一个无参构造函数,代码如下:

#include <iostream>
#include <string>
using namespace std;class Student{private:int age;string name;string sex;public:	Student(){age = 0;name = "test";sex = "male";}void display(){cout <<"name:" <<name <<", age:" <<age <<", sex:" <<sex <<endl;}
};int main(){Student s;s.display();return 0;
}

        此时参数已在构造函数中初始化,执行效果如下:

三、构造函数的重载

        在一个类中可以定义多个构造函数,以便对类对象提供不同的初始化的方法供用户选择。这些构造函数名称相同,而参数的个数或参数类型不同,这称为构造函数的重载。代码如下:

#include <iostream>
#include <string>
using namespace std;class Student{private:int age;string name;string sex;public:	// 不带参数构造函数Student(){age = 0;name = "test";sex = "male";}// 带参的构造函数Student(int a, string n, string s){age = a;name = n;sex = s;}void display(){cout <<"name:" <<name <<", age:" <<age <<", sex:" <<sex <<endl;}
};int main(){Student s, s2(10, "jack", "male");s.display();s2.display();return 0;
}

        运行结果如下:

四、参数初始化表

        C++提供了一种特殊的初始化数据成员方法(参数初始化表来实现对数据成员的初始化),这种方法不在函数体内实现数据的初始化,而在函数首部实现。代码如下:

#include <iostream>
#include <string>
using namespace std;class Student{private:int age;string name;string sex;public:	// 不带参数构造函数Student(){age = 0;name = "test";sex = "male";}// 带参的构造函数,并且使用参数初始化表对数据成员的初始化Student(int a, string n, string s) : age(a), name(n), sex(s){}void display(){cout <<"name:" <<name <<", age:" <<age <<", sex:" <<sex <<endl;}
};int main(){Student s, s2(10, "jack", "male");s.display();s2.display();return 0;
}

        这种写法方便、简练,尤其当需要初始化的数据成员较多时更显其优势。运行结果如下:

五、类体外定义构造函数

        除在类内定义构造函数,也可以在类外定义构造函数,要类名加上两个冒号“::”域限定符来实现。代码如下:

#include <iostream>
#include <string>
using namespace std;class Student{private:int age;string name;string sex;public:	// 声明不带参数构造函数Student();// 带参的构造函数,并且使用参数初始化表对数据成员的初始化Student(int, string, string);void display(){cout <<"name:" <<name <<", age:" <<age <<", sex:" <<sex <<endl;}
};int main(){Student s, s2(10, "jack", "male");s.display();s2.display();return 0;
}// 类体外定义无参构造函数
Student::Student(){age = 0;name = "test";sex = "male";
}
// 在类体外定义带参构造函数
Student::Student(int a, string n, string s) : age(a), name(n), sex(s){}

        运行结果如下:

六、构造函数添加默认参数

        在成员函数中可以使用有默认的参数,构造函数也可以使用包含默认参数的构造函数。代码如下:

Student::Student(int a = 15, string n = "Tom", string s = "female") : age(a), name(n), sex(s){}

        如果构造函数全部参数都指定了默认值,则在定义对象时可以给一个或几个实参,也可以不给出实参;但应该执行哪一个构造函数,会出现歧义,系统无法识别编译时会报错([Error] no matching function for call to 'Student::Student()')。这块操作对程序员来说,开发难度会加大,所以不建议使用。

七、析构函数

        析构函数是C++中的一个特殊的成员函数,它的作用与构造函数相反,它的名字是类名前面加一个“~”符号。在以C++中“~”是位取反运算符,所它是与构造函数作用相反的函数。当对象的生命期结束时,会自动执行析构函数。在以下几种情况会执行析构函数:

  1. 在一个函数中定义一个对象,当这个函数被调用结束时,对象应该释放,在对象释放前自动执行析构函数。
  2. static局部对象在函数调用结束时对象并不释放,因此也不调用析构函数,只在main函数结束或调用exit函数结束程序时,才调用static局部对象的析构函数。
  3. 定义了一个全局对象,则在程序的流程离开其作用域时,调用该全局对象的析构函数。
  4. 如果用new运算符动态地建立一个对象,当用delete运算符释放该对象时,先调用该对象的析构函数。

以上几种方法演示代码如下:

#include <iostream>
#include <string>
using namespace std;class Student{private:int age;string name;string sex;public:	// 声明不带参数构造函数Student();// 带参的构造函数,并且使用参数初始化表对数据成员的初始化Student(int, string, string);// 定义析构函数~Student(){cout <<"Destructor called:" <<name <<endl;}void display(){cout <<"name:" <<name <<", age:" <<age <<", sex:" <<sex <<endl;}
};// 对象在函数内执行
void show_student(){Student t1(15, "Lily", "femail");t1.display();
}int main(){// 在函数中定义一个对象执行后,执行析构函数show_student();// 当对象定义全局(如main函数结束),执行析构函数Student s;s.display();// 当static局部对象在main函数结束后,执行析构函数static Student s2(10, "jack", "male");s2.display();// 当用new运算符动态地建立一个对象Student *p = new Student(12, "John", "male");p->display();return 0;
}// 类体外定义无参构造函数
Student::Student(){age = 0;name = "test";sex = "male";
}
// 在类体外定义带参构造函数
Student::Student(int a = 15, string n = "Tom", string s = "female") : age(a), name(n), sex(s){}

        执行后支行结果:

        可以看出,首先show_student()函数执行完后,其内部t1对象已结束并执行析构函数;然后定义全局对象和static局部对象,在main函数执行结束后,也相继执行析构函数;但是始终未见用new运算符动态建立的对象执行析构函数,这是因为没用delete运算符释放对象,现在咱们加再运行看下结果,代码如下:

Student *p = new Student(12, "John", "male");
p->display();
delete p;

        运行结果如下:

        此时用new建立的对象也执行了析构函数,从这也可以看出,John在test、jack之前执行析构函数,恰好说明了定义在全局对象和static局部对象是在main函数执行结束后,执行的析构函数。

c++构造函数与其他开发语言相比,不仅有很多相似之处,也有独特之处。相似之处有其命名中与类同名且无返回类型,自动调用与初始化,可重载性等外,还可以在类体外定义构造函数,参数初始化表,析构函数等。

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

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

相关文章

车载以太网AVB交换机 TSN交换机 时间敏感网络 11口 千兆 SW2000TSN

目录 一、TSN时间敏感交换机概述 二、产品介绍 SW2000M/H TSN 1、产品框架 2、产品特点与参数 产品特点 产品参数 3、配置与使用 4、常用连接方式 4.1 双通道作为监控和数据采集器&#xff0c;采集两个设备间的通信数据&#xff08;Bypass功能&#xff09; 4.2 试验搭…

曲线降采样之道格拉斯-普克算法Douglas–Peucker

曲线降采样之道格拉斯-普克算法Douglas–Peucker 该算法的目的是&#xff0c;给定一条由线段构成的曲线&#xff0c;找到一条点数较少的相似曲线&#xff0c;来近似描述原始的曲线&#xff0c;达到降低时间、空间复杂度和平滑曲线的目的。 附赠自动驾驶学习资料和量产经验&…

Linux安装Tomcat保姆级教程

文章目录 前言一、安装JDK二、Tomcat下载三、Tomcat安装1.创建Tomcat的安装目录2.切换到Tomcat的安装目录3.上传Tomcat安装包4.解压缩5.切换到安装好的tomcat的bin目录6.启动tomcat7.网络请求测试 四、外部电脑访问nginx设置方法一&#xff1a;关闭防火墙方法二&#xff1a;添加…

回顾快速排序

快速排序 快速排序的核心&#xff1a; 找到一个key 通常左边的数比key小&#xff0c;右边的数比key大。 找key通常有三种方法&#xff1a; 1. 挖坑法&#xff1a; 代码实现&#xff1a; // int _pivot(int* a, int left, int right) {int begin left, end right;int in…

数据结构(初阶)第二节:顺序表

从本文正式进入对数据结构的讲解&#xff0c;开始前友友们要有C语言的基础&#xff0c;熟练掌握动态内存管理、结构体、指针等章节&#xff0c;方便后续的学习。 顺序表&#xff08;Sequence List&#xff09; 线性表的概念&#xff1a;线性表&#xff08;linear list&#xff…

ssm016基于 Java Web 的校园驿站管理系统+jsp

校园驿站管理系统的设计与实现 摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对校园快递信息管理混乱&#xff0c;出…

stm32串口的使用

我们先简单介绍一下基本的概念 1数据的通信方式&#xff1a; 2 这里三种数据传输方向分类大家需要记住。后面的通信都会涉及到。 3 我们来看一下常见的通信&#xff0c;这里我们使用usart 一什么是串口 1.1概述 &#xff1a; 指按位发送和接收的接口 但是&#xff0c;rs233…

【“状态机” 解析UART不定长度的协议帧】

【“状态机” 解析UART不定长度的协议帧】 1. 数据帧格式2. 状态机原理3. 代码实现 通信设计中考虑协议的灵活性&#xff0c;经常把协议设计成“不定长度”。如果一个系统接收上述“不定长度”的协议帧&#xff0c;将会有一个挑战–如何高效接收与解析。一个实例如下图&#xf…

【蓝桥杯嵌入式】11届程序题刷题记录及反思

一、题目介绍 按键输入&#xff1a;短按 模拟电压输出&#xff1a;ADC LCD显示 PWM输出&#xff1a;PA6,PA7 二、usr.c #include "usr.h" #include "lcd.h" #include "stdio.h" #include "tim.h" #include "adc.h" /*v…

道本科技智慧合规助力企业转型升级

在当今这个快速变化的商业世界里&#xff0c;企业合规管理已经从一项基本的监管要求转变为推动企业持续发展的关键动力。合规不仅是避免法律麻烦的盾牌&#xff0c;它还充当着引领企业向更高效、更可靠和更可持续方向发展的催化剂。而在实现这一目标的过程中&#xff0c;智慧合…

隐私计算实训营第六讲-隐语PIR介绍及开发实践

隐私计算实训营第六讲-隐语PIR介绍及开发实践 文章目录 隐私计算实训营第六讲-隐语PIR介绍及开发实践1.隐语实现PIR总体介绍1.1按服务器数量分类1.2按查询类型分类 2. Index PIR - SealPIR3. Keyword PIR - Labeled PSI4.隐语PIR功能分层5.隐语PIR后续计划PIR协议开发PIR调用框…

ndk ffmpeg

报错&#xff1a; 解决办法&#xff1a; 报错 解决办法&#xff1a;