C++语言中的类型(二)
——分门别类是简化事物最有效的方式。
C++语言的强大能力的体现在对程序员自定义数据类型的支持。C++语言主要的一个设计目标就是让程序员自定义的数据类型像内置类型一样好用。
一、自定义数据类型
数据类型告诉我们数据的意义以及我们能在数据上执行的操作。因而自定义数据类型把数据及其对应操作组合在一起。
类的定义形式:
class ClassName
{
//数据
…
//操作
…
};
二、类的实例化方式
如何实例化一个类呢?最简单直接的方式就是模具铸造技术。就是把类的定义作为一个模具,铸造出一个个对象。这种方式最直接,也最容易理解,但效率却不高。那么应该如何实例化呢?其实也很简单,同中国的活字印刷术一样,只需要稍微转变一下观念。何必非要坚持对象的内容在物理上的连续性呢,只要对象的内容是完整的,就足够了。因而我们的眼中不再是一页一页的文字(类),而是一个个字(类成员)。
1、按照这种思路,可以把类成员抽象为两种类型
1) 同一类型的所有实例都相同的类成员
这种类成员,一个程序中保存一份就足够了。
2) 同一类型的各个实例不相同的类成员
这种类成员,每个对象都需要一份,以便呈现自己的独特风采。
2、数据成员与成员函数的实例化
(1)数据成员
按照上述对类成员的抽象,数据成员被区分为两类:
1) 属于类的数据成员(static)
一个程序保留一份即可,由类进行初始化。
2) 属于对象的数据成员(默认状态)
每个对象包含一份,由每个对象进行初始化。
(2)成员函数(方法)
其实对于同一类型的所有实例,它们所具有的方法是相同的,即方法只属于类,而不独属于某个对象,因而一个程序中具有一份就足够了。然而由于数据成员具有两种类型,因而C++根据方法对数据成员的操作方式的不同,分为两种类型:
1) 不可以直接(其实并不是真正的直接,下面会谈到)操作属于对象的数据成员(static)
2) 可以直接操作属于对象的数据成员(默认状态)
试图把数据成员和成员函数的分类统一起来,其实反而会带来更多的困扰,因为它们的分类依据本来就不相同。成员函数的分类依据其实很简单,就是this参数(隐式参数)的声明形式不同而已。
1) 常量成员函数(const)
const ClassName *const this;//指向常量对象的常量指针
因而常量函数不能改变对象的数据成员,常量对象不能调用非常量函数(this形参无法初始化)。
2) 静态成员函数(static)
没有声明this参数,因而不可以通过this指针操作对象的成员。
3) 普通成员函数(默认状态)
ClassName *const this;//指向普通对象的常量指针
从这里我们可以看出,本质上,成员函数和其他的函数并没有什么不同(仅仅书写形式上不同而已),都需要借助参数来访问函数之外的对象。
三、读写属性的控制
仅仅把数据和操作简单地组合在一起,还不能称之为是一个真正的类,只能称之为一个代码的集合而已。还需要添加对成员的读写权限。对于自定义类型,C++语言把类的成员的读写属性抽象为两个级别。
1、 特殊读写属性(可见性)的控制
成员的可见性(可见性是对于类外而言)是读写属性中比较特殊的一种,它区分了类内和类外,达到了对数据的封装。成员的可见性具有两个状态(暂不考虑继承,其实有了继承也不过是再增加一个protected而已。):
1) 可见(public)
2) 不可见(private)
为了代码的清晰,C++语言不再依赖默认状态,允许以更明确的方式控制成员的可见性。
2、 普通读写属性的控制
普通级别的读写属性控制和普通变量一样,是专门针对数据成员的。由类的实例化方式可知,无论是类外还是类的成员函数,其实都是通过对象以间接的方式访问其数据成员。因而都是典型的二层结构。

如图A是一个类对象,A包含3个public权限的数据成员:a、b和c。
对于对象A,它和普通变量一样,用const声明其为常量对象,用默认状态声明其为非常量对象。当A为一个常量对象时,相当于在对象的最外层镶了一层特殊的铁皮,只能通过A对A中的数据成员进行读操作,而不能进行写操作。如果变量a、b和c都是默认读写状态,声明A为常量对象就相当于(实际上并不等同,因为常量属性只施加在了外层对象上,只要突破了这层保护,该声明也就没有意义了。)变量a、b和c都是常量了。这样很不灵活,无法对数据成员的读写属性进行精细化控制,因而C++允许类的数据成员具有三种读写状态:
1) 总是仅可读(const)
2) 总是可读写(mutable)
3) 与类对象的声明一致(默认状态)
这样,我们就可以对任一个数据成员施加我们期望的读写权限了。
四、类型间沟通的门户
我们把事物分割在一个个相互隔离的框架内,既是为了简化问题,也是为了安全。但不同事物间是需要沟通的,因而C++语言在设置了一个个条条框框之后也开辟了几个门户,以达到沟通的目的,同时又可以设置重兵监督把守。
C++语言中的门户主要有以下几种:
1) 类型转换
通过定义转换构造函数,可以实现不同类型间的转换。但需要注意的是,与内置数据类型不同,一般的类型之间并没有那么强的联系,因而类型转换往往是没有必要的,而且会带来很大的安全风险。因此,通常情况下,应该抑制类型间的转换,把转换构造函数声明为explicit。
2) 成员函数
上面说到了,类型转换是危险的,而且往往是没有必要的。当两个类型间只有一种操作有联系时,定义一个函数应该是最合适的。
3) 友元
类的公共接口的设计应当是满足用户最常见的一般性需求。但是有一般的用户,肯定就有一些需求刁钻的用户。为了满足所有用户的需求,而把类设计得异常庞大是没有必要的。于是C++提供了友元,授予友元对类的所有成员的访问权限。通过友元,你可以如设计成员函数一样,设计出满足自己需求的高效接口,同时又不改变类的一般结构。可以说,友元提出的初衷是非常好的,但是这种不负责任的态度却也是危险的——你给别人开了后门,然后就理所当然地撒手不管了,那么有心人就可能背地里干些坏事了。
C++语言中的类型(二)的更多相关文章
- 以杨辉三角为例,从内存角度简单分析C语言中的动态二维数组
学C语言,一定绕不过指针这一大难关,而指针最让人头疼的就是各种指向关系,一阶的指针还比较容易掌握,但一旦阶数一高,就很容易理不清楚其中的指向关系,现在我将通过杨辉三角为例,我会用四种方法从内存的角度简 ...
- C语言中如何将二维数组作为函数的参数传递
今天写程序的时候要用到二维数组作参数传给一个函数,我发现将二维数组作参数进行传递还不是想象得那么简单里,但是最后我也解决了遇到的问题,所以这篇文章主要介绍如何处理二维数组当作参数传递的情况,希望大家不 ...
- C语言中不同类型的循环(Different types of loops in C)
C语言中有三种类型的循环:for,while,do-while. while循环先判断循环条件. while (condition) { //gets executed after condition ...
- C++语言中的类型(一)
--分门别类是简化事物最有效的方式. 类型是C++语言的基础,对象类型决定了能对该对象进行的操作. 一.基本内置数据类型 C++预先定义的基本内置数据类型是构造世界万物的原子,数据类型告诉我们数据的意 ...
- C语言中的指针(二)
指针指向谁,就把谁的地址赋给指针,指针变量和指针指向的内存变量是不一样的.不停的给指针赋值,相当于是不断的改变指针的指向. 在开发中要避免野指针的存在,在指针使用完毕之后,记得要给指针赋值成为NULL ...
- C#语言中的类型转换方法(unfinished)
一.C#中的数据类型 1.数值类型 2.字符类型 3.字符串类型 4.布尔类型 5.枚举类型 6.Object类型 二.常见的类型转换 从转换方式的角度,类型转换分为隐式转换与显式转换两种. 其中,隐 ...
- php弱类型语言中的类型判断
1.php一个数字和一个字符串进行比较或者进行运算时,PHP会把字符串转换成数字再进行比较.PHP转换的规则的是:若字符串以数字开头,则取开头数字作为转换结果,若无则输出0. 例如:123abc转换后 ...
- C语言中不同类型的数据转换规则
不同类型数据间的混合运算与类型转换 1.自动类型转换 在C语言中,自动类型转换遵循以下规则: ①若参与运算量的类型不同,则先转换成同一类型,然后进行运算 ②转换按数据长度增加的方向进行,以保证精度不降 ...
- 关于C语言中不同类型数据进行计算 有符号和无符号数进行计算
float是8个有效位, 做个试验: 输出如下: 上面说明了什么: 1, 18/2.2 是除不尽的, 因为是define,所以没有给ratio变量赋值类型,但是从sizeof输出的结果是8,所以系统默 ...
随机推荐
- Django REST FrameWork中文教程3:基于类的视图
我们也可以使用基于类的视图编写我们的API视图,而不是基于函数的视图.我们将看到这是一个强大的模式,允许我们重用常用功能,并帮助我们保持代码DRY. 使用基于类的视图重写我们的API 我们将首先将根视 ...
- Mysql [Err] 1293 there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
问题: mysql数据 导入数据出错 [Err] 1293 - Incorrect table definition; there can be only one TIMESTAMP column w ...
- 解决网络通信中外网和内网之间的通信问题(NAT转换)
本文原址 http://www.cnblogs.com/lidabo/p/3828846.html 在网络编码中会发现程序在局域网中是可以适用的,但是在外网与内网之间和内网与内网之间就不可行.问题就在 ...
- Android基础知识03—Activity的基本用法
------Activity 活动------ 活动 Activity 是一种包含用户界面的组件,即一个界面就是一个活动 创建活动的过程: >> 创建一个类,继承自Activity类,并且 ...
- 《Unity3D/2D游戏开发从0到1(第二版本)》 书稿完结总结
前几天,个人著作<Unity3D/2D游戏开发从0到1(第二版)>经过七八个月的技术准备以及近3个月的日夜编写,在十一长假后终于完稿.今天抽出一点时间来,给广大热心小伙伴们汇报一下书籍概况 ...
- Yii2之类自动加载
在yii中,程序中需要使用到的类无需事先加载其类文件,在使用的时候才自动定位类文件位置并加载之,这么高效的运行方式得益于yii的类自动加载机制. Yii的类自动加载实际上使用的是PHP的类自动加载,所 ...
- 网络库Alamofire使用方法学习笔记
Github地址 由于Alamofire是swift网络库,所以,以下的所有介绍均基于swift项目 导入Alamofire 以下为使用cocoapods导入,其余的方式请参考官网 source 'h ...
- Python爬虫之爬取慕课网课程评分
BS是什么? BeautifulSoup是一个基于标签的文本解析工具.可以根据标签提取想要的内容,很适合处理html和xml这类语言文本.如果你希望了解更多关于BS的介绍和用法,请看Beautiful ...
- python 带小数点时间格式化
#获取带小数点的时间>>> import datetime #当前时间加3天 >>> t1 = datetime.datetime.now() + datetime ...
- MySQL冗余和重复索引
MySQL允许在相同列上创建多个索引,无论是有意还是无意,mysql需要单独维护重复的索引,并且优化器在优化查询的时候也需要逐个地进行考虑,这会影响性能. 重复索引是指的在相同的列上按照相同的顺序创建 ...