从结构struct谈到类class(基于C++实现)
深入理解struct
在C语言中,我们通常使用struct来表示不同数据类型的结合。当然我们也可以在struct中定义函数,在C++中,这是允许的但是不提倡使用,因为有一个比它更好使用的复杂数据类型,叫做类(这在稍后做出介绍)。
使用struct的时候有一个问题:在进行一个比较大的项目工程的时候,我们的数据结构的定义和使用可能在不同的文件中,当我们修改了数据结构中的某个成员,那么,使用该数据结构的函数必须修改,而我们并不知道拿下函数使用该种数据结构,这时候我们怎么做?答案很简单,在函数定义的时候,让该函数属于该数据结构,在再次查找修改函数的时候,只要属于该结构的函数就进行修改就好了,代码如下:
声明数据结构: struct Time{ int hour; int minute; int second; void set_time(int h, int m, int s); void tick(); void show(); void run(); }; 定义函数: void Time::set_time(int h, int m, int s){} void Time::tick(){} void Time::show(){} void Time::run(){}
补充:成员运算符:表示某个变量的成员,‘.’;表示某个类型的成员,“::”;
类的引出
这样定义就万事大吉了吗?我们如果在其他函数中试图访问该结构中的成员变量(如:hour、minute、second)是成功的,这样我们就有可能无意中修改了数据结构中的某个成员变量的值,当其他函数在使用成员变量的时候,就会使用该可能非法的数据,这样我们就会想到只要让这些成员变量变成私有的就好了,这样除了结构中定义的函数外,其他方式都不可以访问到该成员,这就出现了我们C++常使用的一种数据结构——类。我们进行如下修改。
声明数据结构: class Time{ int hour; int minute; int second; void set_time(int h, int m, int s); void tick(); void show(); void run(); }; 定义函数: void Time::set_time(int h, int m, int s){} void Time::tick(){} void Time::show(){} void Time::run(){}
如果我们就止步于上面的数据结构,我们定义一个上述类的对象,当我们通过对象调用函数的时候,会发现编译不会通过,提示我们“你访问的对象是私有的”。这里就要说明class和struct最大的区别:struct中的所有成员默认是公开的(public),即任意一个函数都可以进行访问;class中的所有成员默认是私有的(private),即除了class中的成员函数之外,其他方式不可以访问。
我们使用class而不是用struct的原因是因为,我们想让成员变量变成私有的,实现基本数据封装。但是对于成员函数的调用接口我们不必要私有,因为我们创建的对象,要通过成员函数完成项目任务,所以我们应让成员函数的接口公开(public),这就是我们常说的封装。接着进行如下更改,让成员函数变量公有的(public)。
声明数据结构: class Time{ private: int hour; int minute; int second; public: void set_time(int h, int m, int s); void tick(); void show(); void run(); }; 定义函数: void Time::set_time(int h, int m, int s){} void Time::tick(){} void Time::show(){} void Time::run(){}
在这里我们要说说class中成员变量的访问权限:
(1)private:私有的。这是class中成员变量默认的访问权限,这种权限的成员变量,只有该类中成员函数可以访问,子类中的成员函数不可以访问,其他方式也不可以访问。(子类是继承中的概念,在讲继承的时候再谈这个话题,先了解就好)。
(2)protected:保护的。该class中的成员函数可以访问,子类中的成员函数也可以访问,但是其他方式不可以访问。
(3)public:公开的。该class中的成员函数可以访问,子类中的成员函数也可以访问,其他方式亦可以访问。
构造函数和析构函数
对于class中的成员函数,我们可以自己写一个函数进行初始化,比如set函数,将每个成员变量进行初始化赋值。但是每次创建一个新类都要调用该种函数进行成员的初始化,这大大加大了我们创建使用类的代价,为了让我们每次创建一个对象的时候,都可以自动调用某个函数进行成员变量的初始化,我们可以使用类中重要的成员函数——构造函数(构造函数无返回值,并且函数名与类名一致),它可以在创建对象的时候自动调用,根据创建对象时传入的初始化参数进行成员变量的初始化。
构造函数的格式:Class_name(parameters){}
构造函数的初始化有两种方式:
(1)通过在构造函数内部进行赋值进行初始化,常量不能被赋值,只能使用初始化列表。
(2)通过初始化列表进行初始化,如果成员变量是数组或结构不能使用初始化列表进行初始化。
构造函数的重载:有时候我们需要定义多个构造函数,因为我们可能基于不同的需求对成员变量的初始化操作不同,这就是构造函数的重载(函数重载:函数名相同,但是函数参数不同。系统可以根据传入参数的不同来调用不同的函数)。
析构函数:存在构造函数也就会存在析构函数,析构函数就是在该对象即将被释放的时候做收尾动作,析构函数一定没有参数列表,所以析构函数不可以重载。
析构函数规则:~Class_name(){};
class A{ int n; double d; public : A():n(0),d(0.0){ // constructor_init1 } A(int n){ // constructor_init2 this->n = n; d = 0.0; } void show(){ cout << "n = " << n << ", d = " << d << endl; } ~A(){ cout << “~A()” << endl; } }; int main(int ac, char *av[]) { A a1; // use constructor_init1 a1.show(); A a2(100); // use constructor_init2 (*this).show(); return 0; }
this指针:this指针是系统自动定义的,用来保存结构变量的地址。当我们创建一个对象的时候,系统就会自动将该对象对应的类的成员保存在this中,我们可以通过this->mem_val或this->mem_func,来访问该成员。在一个成员函数中,可以不用写this,表示默认使用该成员函数所在类的成员变量。
构造函数总结:
(1)构造函数不同写返回值,其函数名与类名一致。
(2)构造函数在每个对象创建的时候都不被自动调用一次。
构造函数的调用顺序
·全局对象的构造函数在main之前调用。
·静态局部对象的构造函数在整个程序的执行过程中只调用一次。
class A{ int n; public: A(int n) : n(n){ cout << "A(" << n << ')' << endl; } ~A(){ cout << "~A(" << n << ')' << endl; } }; void func(){ A a2(2); static A a3(3); } int main(int ac, char *av[]) { A a4(4); cout << "first call func : \n"; func(); cout << "second call func : \n"; func(); return 0; } A a1(1); //========================== // 1:全局对象 // 2:函数func中的自动对象 // 3:函数func中的静态全局对象 //4:函数main中的自动对象 //=============================== 结果显示: [root@anna-laptop construtor]# ./call_queue A(1) A(4) first call func : A(2) A(3) ~A(2) second call func : A(2) ~A(2) ~A(4) ~A(3) ~A(1)

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Python2.7 smtplib发送带附件邮件报错STARTTLS解决方法
最近在SIOMP系统中添加一项功能时,即自动发送带附件邮件到指定邮箱时,发现在发送时报错:错误信息:STARTTLS extension not supported by server.很是奇怪,但发送无附件邮件时,可以正常发送,且不报错,前期以为是代码存在问题,如果调出对应的错误信息反馈,似乎和代码没有什么关系; 详细代码如下所示: #-*-coding:utf-8-*- importemail fromemail.mime.textimportMIMEText fromemail.mime.multipartimportMIMEMultipart importsmtplib mailsenduser="report@lidongni.com" mailreceiveuser="lidongni@lidongni.com" mailhead="TEST邮件" mailcontent="测试邮件" mailsmtpserver="smtp.lidongni.com" mailsenduser1="report" mailsenduserpasswd="789456123" filep...
- 下一篇
Cobbler:自动化安装成千上万台服务器实战!!!
作者:付炜超 项目背景: 在我们的公司刚买了一大批服务器,这个时候需要你全部安装成linux环境的系统,这个时候你是肯定不愿意一台一台服务器的进行安装。这个时候Cobbler华丽上场。 实验环境: vmware workstation 11 centos6.5的系统下 Cobbler服务器:ip:192.168.0.32 防火墙关闭 setenforce 0 SecureCRT (ssh远程连接软件) 软件介绍: Cobbler 是一个免费开源系统安装部署软件,用于自动化网络安装操作系统;基于Python开发,是对 PXE 的二次封装,提供了 CLI 和 Web 的管理形式,也提供了API接口,方便二次开发使用。 它不仅可以安装物理机,同时也支持虚拟化、GuestOS的安装。另外,Cobbler还能结合 Puppet 等集中化管理软件,实现自动化管理。 项目实施流程: 一、相关的软件包安装 [root@Master ~]# yum install -y cobbler pykickstart debmirror dhcp rsync cman fence-agents 二、htt...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Windows10,CentOS7,CentOS8安装Nodejs环境
- MySQL8.0.19开启GTID主从同步CentOS8
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Hadoop3单机部署,实现最简伪集群
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- 设置Eclipse缩进为4个空格,增强代码规范