C++语言体系设计哲学的一些随想(未完待续)

对于静态类型语言,其本质目标在于恰当地操作数据,得到期望的值。具体而言,需要:

(1)定义数据类型

你定义的数据是什么,是整形还是浮点还是字符。该类型的数据可以包含的值的范围是什么。

(2)定义操作的含义

操作是严格数据类型相关的。操作表明了对了一个具有特定类型的数据,执行操作后产生什么样结果。

===========================================

C++就是一个典型的静态类型语言。在C++中,无论是"数据类型"还是"操作",都分为内置的和自定义的。

C++的内置数据类型包括:

(1)基本内置类型

整形、浮点、布尔、字符....

(2)STL库定义的类型

例如常用的iostream、string、迭代器......

此外C++和定义了复合类型机制,包括所有类型的引用、指针、数组,他们可以作为一个完整数据类型的一部分。

顺便提一下,顶层/底层const、static、volatile...等修饰符,定义了数据的其他属性,这些属性也可以是一个完整数据类型的组成部分。

自定义类型,最常用的就是class、struct、union定义,还有函数签名,当然也可以使用复合类型机制定义自己类的引用、指针、数组等。

==============================

重点在于,无论是变量还是常量,必须属于某一特定的数据类型。因为操作只有基于精确的数据类型,其定义才有了确定的含义(在编译原理中叫做“语义”)。也就是说,在一个确定的操作集合中(例如C++语言内置的所有操作),只要给一个变量赋于了数据类型,这个变量可以执行的操作也就确定了。定义变量nVal为int类型,那么nVal就可以参与加减乘除、关系运算、拷贝、转换为double、传递给函数形参、作为数组的下标.........

C++的“操作”,其含义非常广泛。其实C++语言已经通过成员函数、操作符重载、函数重载、构造函数定义的隐式类型转换...等机制,表明了 C++作为一个静态类型语言的本质:属于特定类型的数据,加上其上的操作。可以这样理解,任何一个操作,本质就是函数,操作符在C++语言内部也是被当作函数来看待的(这也能解释C++提供operator操作符重载机制的动机);类的成员函数、友元函数,也是对类本身这个“数据类型”的操作。

更进一步,操作本身也是一种特殊的数据类型。可以定义函数的指针、函数的数组,成员访问(->*,.*),只是可以被当作数据类型来使用的机会不多,也被语言本身限制了。

C++的内置操作不太好理解,实际上我们常用的语言机制都是“操作”,具体包含了:

(1)各种各样的操作符

算术操作符、关系操作符、位运算、取地址、单目运算、解引用、数组元素访问.....

(2)拷贝操作

拷贝初始化、列表初始化(C++ 11)、赋值运算、函数传参、函数返回值、类型转换执行的临时变量拷贝......等其他非引用场景

(3)数据类型转换

类型转换也是一种操作。对于普通的操作,执行前需先匹配要操作的数据的类型。现实中,不可能总能保证在代码里提供类型严格匹配的数据,因此类型转换也是C++语言非常普遍的操作。

该如何理解这样的操作呢?举个例子,例如:

int nVal = 42;

double fVal = 3.14;

double fValTwo;

fValTwo = fVal + nVal ; // nVal类型提升为double

上述代码最后一行的相加操作将执行类型提升。从编译器的角度看,此时将生成一个匿名的变量,变量的类新和需要匹配的类型(double)相同,之后执行int至double的类型转换操作,操作结果保存在这个匿名变量中。之后才会执行“+”操作。也就是说,如果选定了操作,那么就会期待若干数据类型完全匹配的操作数,为了满足这个条件,系统会执行类型转换。

对于赋值操作,该操作会期待=右边操作数的数据类型和左边完全匹配,此时也会和上述相同,生成匿名变量,执行类型转换。准备工作完成后,再执行"="操作。

函数的调用也是基于相同的原理,即实参类型和形参类型的匹配。

... ...

C++语言内部定义了异常复杂的类型转换规则(操作),只不过大多数对使用者是透明的。例如:

整形提升 - char、short、bool会先转换为int;

类型提升 - 防止精度损失;

类型降低 -有精度损失,常见于拷贝操作。拷贝操作是将源对象严格匹配目标对象,因此不会有算术操作里的“整形提升”。拷贝包括了拷贝初始化、赋值运算、函数调用实参赋给形参

非bool值都可以转换为bool,相反则转换为0/1;

任意类新指针都可转换为void*;

数组在不用于decltype、sizeof、typeid、取地址&的情况下,会自动转换为指向第一个元素的指针。

非底层const向底层const的转换 - 指向常量的引用和指针可以绑定到非常量上,和内置类型的提升与降低不同,底层const向非底层const的转换是非法的

子类向基类的转换 - 基类指针/引用可以指向子类,这是多态的基础。和底层const一样,相反的转换是非法的

... ...

-

PS:关于底层const和继承体系类型转换的单向性:

本质而言,一个数据的数据类型,可以执行的操作的集合越小,该数据可以引用/绑定的对象类型越广。例如:

数据类型A,可以执行operA - operZ 共26个操作。数据类新B,可以执行的操作是A的子集,比如operH-operN。那么,B的引用/指针可以绑定到A(B的引用/指针可以接受A/A的指针赋值),相反则是非法的。

const int *不能修改指向的int,而int *可以,也就是说,数据类型const int *的操作范围比int *要小,所以const int *可以绑定到int*指向的对象(本质上是指const int *可以接受int*赋值)。
在继承体系中,基类的操作范围肯定是小于子类的,所以 基类指针指向/基类引用 子类的合法的。

造成这一切的原因就在于,对静态类型语言,编译器始终“固执”地、“自以为是”地按照其静态声明类型,来决定一个操作是否合法,而不去管这个对象实际指向的类型。可以想象,编译器“自以为是”地认为通过int *可以改变这个int,而不管这个int*实际指向的是const int,如果允许底层const向非底层const转换,就会带来冲突。

-

PS:基于该观点理解重载

函数重载、操作符重载的本质,是用同一个名字定义了多个操作。结果是在编译阶段引入了一个确定具体操作的过程 - 从候选操作中选出最匹配的操作。而上述“类型转换”操作则是在运行阶段进行的。

自定义操作,包括我们定义的普通函数、成员函数、重载的操作符、构造函数定义的隐式类型转换、拷贝构造函数定义的拷贝操作...

未完待续

时间: 2024-07-30 10:17:05

C++语言体系设计哲学的一些随想(未完待续)的相关文章

把握linux内核设计思想系列(未完待续......)

[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途] 把握linux内核设计思想(一):系统调用 把握linux内核设计思想(二):硬中断及中断处理 把握linux内核设计思想(三):下半部机制之软中断 把握linux内核设计思想(四):下半部机制之tasklet 把握linux内核设计思想(五):下半部机制之工作队列及几种机制的选择 把握linux内核设计思想(六):内核时钟中断 把握linux内核设计思想(七):内核定时器和

防撞灯测试仪的设计(未完待续)

频闪灯又叫防撞灯,顾名思义,它的作用是防止飞机发生碰撞.科技发展到现在,飞机防撞的系统有很多比如TACS.应答机等都具有防止飞机相撞的功能.防撞灯跟这些复杂的系统比起来显得非常原始,但是它的作用还是非常值得肯定的.要不然适航法规就不会强制飞机安装防撞灯了.要辨别防撞灯也很简单,晚上抬头看飞机,一闪一闪的就是它.民航飞机上还可以看到有颜色区别(左红又绿尾部白). 防撞灯一般都是氙气频闪灯.在飞机上工作时,都有标配的频闪的电源.比如波音的60-4983-3,空客的8ES系列频闪灯电源等.都是为频闪灯

[漏洞检测]Proxpy Web Scan设计与实现(未完待续)

Proxpy Web Scan设计与实现 1.简介:          Proxpy Web Scan是基于开源的python漏洞扫描框架wapiti改造的web漏洞扫描器,其主要解决以下几个问题而生: (1).当前互联网业务处于快速发展阶段,由于小版本更新迭代快,很难做到发布前必定经过安全测试.此外,安全小组面临安全人员不足和人工安全测试重复性工作过高的问题, (2).当前业界的漏洞扫描器更多的是基于简单的爬虫加扫描引擎的模式,可定制化幅度小,易用性和可扩展性都不是太好,如果要嵌入到发布流程则

关于自学C语言开始时应该注意的问题分享—未完待续......

---恢复内容开始--- 自学C语言编程总结 第1章C语言概述 1.     如果用户将主函数的返回值类型定义为了void,则不需要返回任何值: 2.     C语言的基本结构包括主函数和程序体两部分,主函数是程序的入口函数main(). 3.     对于C语言的头文件如果是系统定义的,一般用尖括号<> 括起来,如果为自己定义的,那必须用双引号<>括起来.                                        --2018.1.1 第2章 变量和常量 1.

GO语言完整解析GO!GO!GO!(一)基础语法(未完待续)

前言 适用大概用过Golang编程的朋友,本文档属于一份总结,与査漏补缺. 一:GO的数据类型--基础类型 0,定义一个变量的标准格式为: var  变量名   类型 1,数字类 1)整数类型:int8, int16,int32,int64(有符号)/uint8, uint16,uint32,uint64(无符号),分别占用8bit,16bit,32bit,64bit; int/uint,占用多大空间取绝于CPU的机器字大小,一般为32bit或者64bit rune,表示一个字符占用的存储空间

java开发设计数据库细节(未完待续)

1.create_time(创建时间)不能勾选"根据当前时间戳更新",否则每更新一次信息,创建时间就会改变一次.2.update_time(最后一次更新时间)一定要勾选"根据当前时间戳更新",否则每次更新信息,update_time都是不会改变的 原文地址:https://blog.51cto.com/13678728/2456635

Python语言基础与应用 (P23)上机练习:容器类型操作(未完待续)

上机练习:容器类型操作〉 列表.元组基本操作+, *, len(), [], in 1 Python 3.7.0 (default, Jun 28 2018, 08:04:48) [MSC v.1912 64 bit (AMD64)] :: Anaconda, Inc. on win32 2 Type "help", "copyright", "credits" or "license" for more informatio

React的设计哲学 - 简单之美

React最初来自Facebook内部的广告系统项目,项目实施过程中前端开发遇到了巨大挑战,代码变得越来越臃肿且混乱不堪,难以维护.于是痛定思痛,他们决定抛开很多所谓的“最佳实践”,重新思考前端界面的构建方式,于是就有了React. React带来了很多开创性的思路来构建前端界面,虽然选择React的最重要原因之一是性能,但是相关技术背后的设计思想更值得我们去思考.之前我也曾写过一篇React的入门文章,并提供了示例代码,大家可以结合参考. 上个月React发布了最新的0.13版,并提供了对ES

深入浅出React(一):React的设计哲学 - 简单之美

编者按:自2013年Facebook发布以来,React吸引了越来越多的开发者,基于它的衍生技术,如React Native.React Canvas等也层出不穷.InfoQ精心策划"深入浅出React"系列文章,为读者剖析React开发的技术细节. React最初来自Facebook内部的广告系统项目,项目实施过程中前端开发遇到了巨大挑战,代码变得越来越臃肿且混乱不堪,难以维护.于是痛定思痛,他们决定抛开很多所谓的"最佳实践",重新思考前端界面的构建方式,于是就有