C++之类和对象的使用(三)
对象数组
如果构造函数只有一个参数,在定义数组时可以直接在等号后面的花括号内提供。Student stud[3]={90,92,01};//合法
如果构造函数有多个参数,则不能用在定义时直接所提供所有实参的方法。
但可以如下定义:
- //构造函数有三个参数:学号,年龄,成绩
- Student stud[]{
- Student(,,);
- Student(,,);
- Student(,,);
- };
对象指针
指向对象的指针
- class Box
- {public:
- Box(int h=,int w=,int len=);
int s;- int volume();
- private:
- int height;
- int width;
- int length;
- };
- Box::Box(int h,int w,int len)
- {
- height=h;
- width=w;
- length=len;
- }
- int Box::volume(){
- return(height*width*length);
- }
Box *ptr;//定义指向对象的指针
Box t1;//定义Time类对象
ptr=&t1;//将t1的起始地址赋给ptr
指向对象成员的指针
1)指向对象数据成员的指针
定义的一般形式为:
数据类型名 *指针变量名;
- int *p1;
- p1=&t1.s;// s是public类型数据,则可以在类外通过指向对象数据成员的指针变量访问对象数据成员s
cout<<*p1<<endl;//输出t1.hour的值
2)指向对象成员函数的指针
定义指向对象成员函数的指针变量和定义指向普通函数的指针变量方法有所不同。对比如下:
- 类型名(*指针变量名)(参数列表);
- void (*p)( );
- p=fun;
- (*p)( );//调用普通fun函数
- //////////////////////////////////////////
- 针对指向对象成员函数的指针要求:指针变量的类型必须与赋值号右侧函数的类型匹配,满足一下3个方面
- )函数参数的类型和参数个数
- )函数返回值的类型
- )所属的类
- 采用如下格式:
- 一般形式为:
- 数据类型名(类名::*指针变量名)(参数列表);
- void(Time::*p2)();//定义指向对象公用成员函数的指针变量
使指针变量指向一个公用成员函数的一般形式为 指针变量名=&类名::成员函数名
p2=&Time::get_time;
(t1.*p2)();//调用成员函数
- #include<iostream>
- using namespace std;
- class Time
- {public:
- Time(int,int,int);
- int hour;
- int minute;
- int sec;
- void get_time();
- };
- Time::Time(int h,int m,int s)
- {
- hour=h;
- minute=m;
- sec=s;
- }
- void Time::get_time(){
- cout<<hour<<":"<<minute<<":"<<sec<<endl;
- }
- int main()
- {
- Time t1(,,);
- int *p1=&t1.hour;
- cout<<*p1<<endl;
- t1.get_time();
- Time *p2=&t1;
- p2->get_time();
- void(Time::*p3)();//定义指向Time类公用成员函数的指针变量p3
- p3=&Time::get_time;//使p3指向Time类公用成员函数get_time
- (t1.*p3)();//调用p3指向的成员函数(t1.get_time);不应写成p3=&ti.get_time(成员函数不是存放在对象的空间中的,而是存放在对象外的空间中的。)
- } // main函数第8.9两行可以写成一行void(Time::*p3)()=&Time::get_time
this指针
在每一个成员函数中都包含一个特殊的指针,这个指针的名字是固定的,称为this指针。
它是指向本类对象的指针,它的值是当前被调用的成员函数所在的对象的起始地址。
- //当调用a.volume时候,实际 上执行
- (a.height)*(a.width)*(a.length)
公用数据的保护
既要使数据能在一定范围内共享,又保证它不被任意修改,这是可以把有关的数据定义为常量。
常对象
可以在定义对象的时候加关键字const,指定对象为常对象。常对象必须要有初值,如
- Time const t1(,,);
这样对象t1中的所有数据成员的值都不能被修改。
类名 const 对象名(实参表)或者 const 类名 对象名(实参表)
Tips:
1)如果一个对象被声明为常对象,则通过该对象只能调用它的常成员函数,而不能调用该对象的普通成员函数(除了析构函数和构造函数)。常成员函数时常对象唯一的对外接口。
引用常对象中的数据成员,只须将该成员函数声明为const即可。 void get_time() const;
2)常成员函数可以访问常对象中的数据成员,但仍然不能修改其值。若对数据成员声明为mutable,可以被修改。
以上两点保证常对象中数据成员的值绝对不会改变。
常对象成员(数据成员和函数成员)
常数据成员
其作用和用法与一般常变量相似,用关键字const来声明常数据成员。其值不可修改;
只能通过构造函数的参数初始化表对常数据成员进行初始化,任何其他函数都不能对常数据成员赋值。
常成员函数
如果将成员函数声明为常成员函数,则只能引用本类中的数据成员,而不能修改它们。
声明常成员函数的一般形式:
类型名 函数名 (参数表)const
const是函数类型的一部分,在声明函数和定义函数时都要有const关键字,在调用时不必加const。常成员函数可以引用const数据成员,也可以引用非const的数据成员。
不用误以为常对象中的成员函数都是常成员函数,常对象只保证其数据成员是常数据成员,其值不被修改。如果在常对象中的成员函数未加const声明,系统把它编译为非const成员函数。
常成员函数不能调用另一个非const成员函数。
指向对象的常指针
将指针变量声明为const类型,这样指针变量始终保持为初值,不能改变,即其指向不变。
- Time t1(,,),t2;
- Time *const ptr1;
- ptr1=&t1;
- ptr1=&t2;//错误,不能改变ptr1的指向
类名 *const 指针变量名
指向常对象的指针变量
常变量指针
const char *ptr;
定义指向常变量的指针变量的一般形式为:
const 类型名 *指针变量名;
1)如果一个变量已被声明为常变量,只能用指向常变量的指针指向它。
不能用一般的(指向非const型变量的)指针去指向它;如
- const char c[ ]="boy";
- const char *p1;
- p1=c;
- char *p2=c;//不合法,p2不是指向常变量的指针变量
2)指向常变量的指针变量除了可以指向常变量外,还可以指向未被声明为const的变量。此时不能通过此指针变量改变该变量的值。如
- char c1='a';
- const char *p;
- p=&c1;
- *p='b';//非法,不能通过p改变变量c1的值
- c1='b';
3)如果函数的形参是指向非const型变量的指针,实参只能用指向非const变量的指针,而不能用指向const变量的指针。这样,在执行函数的过程中可以改变形参指针变量所指向的变量的值。如果函数的形参是指向const型变量的指针,在执行函数的过程中显然不能改变指针变量所指向的变量的值,因此允许实参是指向const变量的指针,或指向非const变量的指针。如
- const char str[]="boy";
- void fun(char *ptr);
- fun(str);//调用fun函数,实参是const变量的地址,非法
用指针变量作形参时形参和实参的对应关系
对象的常引用
类似于变量的引用
const型数据的总结
对象的动态建立与释放
前面介绍的方法定义的对象都是静态的,在程序运行过程中,对象所占的空间是不能随时释放的。
动态建立对象:要用到对象的时候建立对象,不用的时候就撤销它,释放它所占的内存空间。
如new Box;
编译系统开辟了一段内存空间,并在此空间中存放一个Box类对象,同时调用该类的构造函数,以使该对象初始化。但是此时用户无法访问这个对象,因为这个对象既没有对象名,用户不知道它的地址。这种对象成为无名对象,存在但没有名字。
用new运算符动态地分配内存后,将返回一个指向新对象的指针的值,即所分配的内存空间的起始地址。用户可以获得这个地址,并通过这个地址来访问这个对象。需要定义一个指向本类的对象的指针变量来存放该地址。
- Box *pt;
- pt=new Box;
C++还允许在指向new时,对新建立的对象进行初始化。
- Box *pt = new Box(,,);
这种写法把上面两个语句合并为一个语句,并指定初值。
在不需要使用由new建立的对象时,可以用delete运算符予以释放。
- delete pt;
在执行delete运算符时,在释放内存空间之前,自动调用析构函数,完成有关善后清理工作。
对象的赋值和赋值
对象的赋值
对象名1 = 对象名2
- Student stud1,stud2;
- ....
- ....
- stud2=stud1;
1)对象的赋值只对其中的数据成员赋值,而不对成员函数赋值。不同对象的成员函数 是同一个函数代码段,不需要,也无法对它们赋值。
2)类的数据成员中不能包括动态分配的数据,否则在赋值时可能出现严重后果。
对象的复制
有时需要用到多个完全相同的对象,即对象的复制。类名 对象2(对象1)。如:
- Box box2(box1);//用已有的对象box1去克隆一个新对象box2
C++还提供另一种方便用户的复制形式,用复制号代替括号。
- Box box2=box1;
类名 对象名1=对象名2;
区别对象的复制与赋值:
对象的赋值是对一个已经存在的对象赋值,因此必须先定义被赋值的对象。而对象的复制是从无到有地建立一个新对象,并使它与一个已有的对象完全相同。
静态数据成员:如果想在同类的多个对象之间实现数据共享,也不用使用全局对象,可以用静态的数据成员。
- class Box{
- public:
- int volume();
- private:
- static int height;// 静态的数据成员
- int width;
- int length;
- };
如果希望各对象中的数据成员的值是一样的,就可以把它定义为静态数据成员;
静态数据成员只占用一份空间(而不是每个对象分别为它保留一份空间)。
说明:
1)如果只声明了类而未定义对象,则类的一般数据成员是不占内存空间的,只有在定义对象时,才为对象的数据成员分配空间。但是静态数据成员不属于某一个对象,在为对象所分配的空间中不包括静态数据成员所占用的空间。静态数据成员是在所有对象之外单独开辟空间。只要类中指定了静态数据成员,即使不定义对象,也为静态数据成员分配空间,它可以被引用。
2)静态数据成员是在程序开始运行时被分配空间,到程序结束时才释放空间。
3)静态数据成员可以初始化,但只能在类外进行初始化。
- int Box::height = ;
一般形式为:
数据类型 类名::静态数据成员名=初值;
在初始化时不必加static。不能用参数初始化表对静态数据成员初始化。默认值为0。下面是错误的:
- Box(int h,int w,int len):height(h){}//错误
4)静态数据成员既可以通过对象名引用,也可以通过类名来引用。
- #include<iostream>
- using namespace std;
- class Box
- {public:
- // Box();
- Box(int,int);
- int volume();
- //private:
- static int height;
- int width;
- int length;
- };
- Box::Box(int w,int len)
- {
- width=w;
- length=len;
- }
- int Box::volume(){
- return(height*width*length);
- }
- int Box::height=;//对静态数据成员初始化
- int mian()
- {
- Box box1(,),box2(,);
- //cout<<"the box1 is:"<<box1.volume()<<endl;
- cout<<box1.height<<endl;//通过对象名引用静态数据成员
- cout<<box2.height<<endl;
- // Box box2(14,12,48);
- //cout<<"the box2 is:"<<box2.volume()<<endl;
- cout<<Box::height<<endl;//通过类名引用静态数据成员
- cout<<box1.volume()<<endl;
- // return 0;
- }
可以看到,如果静态数据成员是public型,在类外可以通过对象名引用公用的静态数据成员,也可以通过类名引用静态数据成员。即使没有定义对象,也可以通过类名引用静态数据成员,说明静态数据成员属于类,不属于对象。若是private,则不可在类外直接引用,必须通过公用的成员函数引用。
5)有了静态数据成员,各对象之间的数据有了沟通的渠道,实现数据共享。因此可以不使用全局变量。注意公用静态数据成员与全局变量不同,静态数据成员的作用域只限于定义该类的作用域内。
静态成员函数
成员函数也可以是静态的,在类中声明函数的前面加static即可。
- static int volume();
静态成员函数时类的一部分而不是对象的一部分。如果要在类外调用公用的静态成员函数,要用类名和域运算符“::”。
- Box::volume();
实际上也越小通过对象名调用静态成员函数。如 a.volume( );但这不意味着此函数属于对象a,而只是用a的类型而已。
静态成员函数是为了处理静态数据成员。
C++之类和对象的使用(三)的更多相关文章
- openstack-r版(rocky)搭建基于centos7.4 的openstack swift对象存储服务 三
openstack-r版(rocky)搭建基于centos7.4 的openstack swift对象存储服务 一 openstack-r版(rocky)搭建基于centos7.4 的openstac ...
- Java反射02 : Class对象获取的三种方式和通过反射实例化对象的两种方式
1.Class对象获取的三种方式 本文转载自:https://blog.csdn.net/hanchao5272/article/details/79361463 上一章节已经说过,一般情况下,Jav ...
- Kubernetes 对象管理的三种方式
Kubernetes 中文文档 1. Kubernetes 对象管理的三种方式对比 Kubernetes 中的对象管理方式,根据对象配置信息的位置不同可以分为两大类: 命令式:对象的参数通过命令指定 ...
- php开发面试题---php面向对象详解(对象的主要三个特性)
php开发面试题---php面向对象详解(对象的主要三个特性) 一.总结 一句话总结: 对象的行为:可以对 对象施加那些操作,开灯,关灯就是行为. 对象的形态:当施加那些方法是对象如何响应,颜色,尺寸 ...
- day16-面向对象基础(三)
今日摘要 今天主要整理一下这俩天学习的内容,面向对象也快学完了,深刻的认识到面向对象就是一个思想,怎么把思想理解了,其他也就不是什么事了 1.类的约束 2.类的类方法与静态方法 3.类的反射 4.类的 ...
- Asp.Net WebAPI核心对象解析(三)
对于.NET的分布式应用开发,可以供我们选择的技术和框架比较多,例如webservice,.net remoting,MSMQ,WCF等等技术.对于这些技术很多人都不会陌生,即时没有深入的了解,但是肯 ...
- JavaScript(JS)之Javascript对象DOM(三)
https://www.cnblogs.com/haiyan123/p/7598320.html 一.什么是HTML DOM HTML Document Object Model(文档对象模型) ...
- Javascript中的对象和原型(三)(转载)
在Javascript中的对象和原型(二)中我们提到,用构造函数创建的对象里面,每个对象之间都是独立的,这样就会降低系统资源的利用率,解决这样问题,我们就要用到下面提到的原型对象. 一 原型对象 原型 ...
- java对象中的三种状态和脏检查及刷新缓存机制
瞬时状态 瞬时状态又称临时状态.如果java对象与数据库中的数据没有任何的关联,即此java对象在数据库中没有相关联的记录,此时java对象的状态为瞬时状态,session对于 瞬时状态的ava对象是 ...
- JavaScript高级程序设计--对象创建的三种方法
创建对象的三种方法: 1.工厂模式 工厂模式是软件工程领域广为人知的设计模式,这种模式抽象了创建具体对象的过程.下面是使用工厂函数创建对象的的一个例子. 2.构造函数: 从上面的例子中,我们看到构造函 ...
随机推荐
- sqlcmd导入大数据文件
sqlcmd导入大数据文件 SQLCMD 允许在Windows命令窗中通过命令行提示符运行脚本. 语法如下: sqlcmd [ { { -U <login id> [ -P <p ...
- Boost.Hana
Boost.Hana Boost.Hana 是一个元编程的库.它为不同种类数据的集合以及类型的集合提供了容器和算法. #include <boost/hana.hpp> namespace ...
- CentOS开机卡在进度条,无法正常开机的排查办法
CentOS开机的时候卡在进度条一直进不去 重启,按f5键进度条/命令行界面方式切换,确认卡问题后处理就好 我这边卡在redis服务,设置为开机启动但是一直服务启动不起来 重启按住"e&qu ...
- JAVA中会存在内存泄露吗
所谓内存泄露就是指一个不再被程序使用的对象或变量一直被占据在内存中.java中有垃圾回收机制,它可以保证一对象不再被引用的时候,即对象编程了孤儿的时候,对象将自动被垃圾回收器从内存中清除掉.由于Jav ...
- 向数据库添加学生信息。存放在REQUEST对象里
代码前几天已经发过了,但是程序一直还没运行出来,今天重新建立了一个数据库,才可以,下面补充上数据截图
- git冲突解决方案 Intellij IDEA
一般在团队合作开发一个项目的过程中,经常出现两个人同时修改一个文件然后都向主master提交commit,这样就会产生冲突(conflict),那么这种情况如何解决? 1 新建分支 如果项目的主分支是 ...
- RN项目中关于父子组件的通信
子组件向父组件传递数据 子控件中在相应的函数中.通过props.coallback的回调通知父组件. 父组件调用callback属性时行 绑定,并在方法中去解析使用获取到的值 . //子控件: < ...
- Appuim学习路-Appuim介绍
(学一个东西,总的知道它支持什么.为什么要选择它吧?所以我就去看github上的介绍了.发现大家介绍的来源大多来自于此) Appium是一个开源的自动化框架,是跨平台的,允许所有平台使用同一套AP ...
- Hibernate使用固定值关联表
假设表A与表B需要进行一对一关联,表A的a1字段等于表B的a1字段,同时表B中的b2字段需要为某一固定值,可采取如下方式配置: public class A { private String a; @ ...
- 取消svn add
svn commit之前,add的东西都可以取消. 通过先执行svn cleanup,再执行svn revert --recursive example_folder.