类与函数的规范化写法(一)—HJ-record01

目录

 

从数据与函数角度层面观察C与C++的异同

C语言对数据和函数的处理方式

 C++语言对数据和函数的处理方式

类(class)的分类

带指针的类

不带指针的类

C++ programs 代码基本形式

从输出(Output)层面观察C与C++的异同

Header(头文件)中的防卫式声明

Header(头文件)的布局

类声明部分

函数模板

inline函数

access level(访问级别)

constructor(ctor,构造函数的标准写法)

 overloading(重载:函数可以有很多个)


从数据与函数角度层面观察C与C++的异同

C语言对数据和函数的处理方式

在C语言中,设计程序的时候,肯定会准备一些类型和函数,可以根据每种类型去创建更多的数据出来,而函数作用就是用来处理这些数据的。

但是,由于C语言本身并没有提供某些关键字,导致所创建出来的数据肯定是全局的,因此各个函数,都可以不加以区分的去处理这些被创建出来的数据,这会对后续的具体操作,带来非常大的负面影响。

 C++语言对数据和函数的处理方式

基于以上的弊端,发展成第一个面向对象的语言——C++,基本思路就是把数据和处理这些数据的函数,包在一起,称作class,(这也就是对应的是C语言中的struct,只不过增加了更多的关键字和特性),数据只能由跟其包在一起的函数去处理,其他人不仅没法处理,而且没法看到,这样就避免了数据与函数的混乱。

数据跟函数包在一起,当使用的时候,一这一种形式(class),创建出来一个对象,然后再在这个对象里面进行处理。

 

类(class)的分类

带指针的类

典型代表:string class(字符串类)

不带指针的类

典型代表:complex class(复数类)

C++ programs 代码基本形式

包含主程序(main())的文件一般为".cpp"文件,而函数声明和标准库(一般以".h"文件存放)都是以头文件的形式被主函数所在的程序被包含("include",再进行细分的话:标准库文件是以"#include<>"的形式写,函数声明是以"#incude "" "的形式写)进去使用。

应该注意到是,这些延申文件名(如:".h"或".cpp"),不一定是固定的,在不同的平台上由不同的延申文件名比 如:".hpp",甚至可能没有对应的延申文件名。

从输出(Output)层面观察C与C++的异同

如上两个是对比C++与C在进行输出的时候,是如何操作的,体会一下,在C++风格输出数据的时候,直接往cout中"丢"数据就可以了!而在C风格的输出方式中,必须指定输出变量的类型才可以,否则会报错。相比之下,C++风格的输出方式就更加的简便了!

Header(头文件)中的防卫式声明

比如,我现在想写一个复数的类型,那么首先,我就需要把复数的类型定义到头文件里面。对于头文件有一种非常正规的写法,是一定要掌握的:

为什么要这样写呢?这是因为,有很多程序要用到你写的这个头文件,或者说,有程序也可能会用到这个头文件和其他的头文件,那么如果对要用到头文件的程序员要求,必须按照某种特定的顺序去include头文件的话,是非常低效的,所以,要将头文件设计成当被include的时候,无论头文件的顺序如何,都不会影响使用的效果才可以,为了达到这个需求,才必须写成如上的防卫式声明。可以将"#include __COMPLEX__"和"#include __COMPLEX__"理解成两个命令,就是直接告诉编译器说:一进来,如果不曾经定义过"__COMPLEX__"这个名词的话,就把这个名词"__COMPLEX__"给定义出来,然后,再开始执行主体的代码,直到运行到"#endif",文件运行结束。这样就保证了,在同一个程序而言,重复include这个头文件的时候,如果这个头文件之前被调用过了,就不会再重复被调用了!所以建议大家,写的任何头文件,都要加上这种防卫式的声明。

Header(头文件)的布局

开始考虑头文件的布局,将头文件的具体内容可以分为三个部分:前置声明、类声明和头定义。其中最重要的是类声明和头定义,至于位置最靠前的前置声明,是在写完类声明和头定义之后,才发现有一些东西是需要在前面声明过才可以,于是把前置声明再给"补上"。

类声明部分

那么首先看对应的"序号1"对应的部分,那就正式开始进入语法的部分,任何一个class都有一个"头"(class head)和"身体"(class body),而在class body里面是类的具体设计:

函数模板

在设计的这个复数类的时候,就开始想,一个复数,最主要的部分就是它的实部和虚部的值,那么在这个类当中,我将实部设定为变量re,虚部设定为变量im,这两个变量都设置为double的类型。那么问题来了,如果我遇到的一个数据,其类型恰好就不是double类型的,这该咋办呢?难道就是再写一个类,只不过把实部和虚部的值定义成int?或者再写一个类再把实部和虚部的值定义成float?可能真把这些类创建出来了,会发现,这些类其实99%都是相同的,就在定义的时候有些许的差别。这不就是在低效的一种做重复的事情吗?这个时候就导入了一个概念——模板(class template)。我现在的需求是,不要把实部和虚部的类型给写死,而是,等到我用的时候再指定,那我就用模板来解决这个问题:

使用者调用的时候再指定类型:

inline函数

如果函数定义在class body里面,可以将其看作为一个inline函数候选人,可以理解成,定义在class body中的函数,很大的概率上被当作内联函数来处理, 内联函数的优势是运行速度很快,类似于C中的宏的概念,但是,并不能把所有函数都写成内联函数,这是因为,如果函数太复杂,是没办法inline的。即便强加了inline关键字(相当于仅作建议),执不执行还取决于编译器的判断。

access level(访问级别)

在class body中,可以大致区分为某几大段,就是用过public、private、protected这三个关键字进行区分。

 使用情况:

左边的调用是错误的,右边是正确的,因为私有对象是无法在外界直接访问,而公有对象可以。 所有的数据都应该放在private,觉得可以让外界调用的函数,放在public中。

constructor(ctor,构造函数的标准写法)

C++中,如果想创建一个对象,那么有一个函数会自动的调用起来,而且,使用者也不可能通过调用函数的方式去跳过对象直接去调用这个函数函数,这个函数就叫构造函数,这种构造函数的写法很独特,比如,1)函数的名称一定要和类的名称一样;2)构造函数可以拥有参数;3)参数还可以有默认值;4)构造函数没有返回类型!

这里就要介绍到一个关于构造函数的,很大气的写法,我们一般写构造函数的时候,都会像写普通函数那样写:

这样写,不是说错,也是正确的,但对于纯属的程序员来言,有点low,宜换一种更规范、更大气的写法来写构造函数:

这种方式是构造函数独有的写法,很简洁,很大气,其中,在函数头又默认的实参,在冒号后面是设置初始化的一行。上面这种将其分成了三行,其实,就算写成一行也是无所谓的,比如:

	ListNode(int x) : val(x), next(NULL) {}

这样也是按照上面的写法,把构造函数写到了一行里面。 判断程序员够不够资格,其中一个判断点就是,看他写的代码能不能充分运用这种写法

那么,这种特殊写法为什么要比普通写法好呢?这是因为,对于一个变量而言,其数值的设定,有两个阶段,一个阶段是初始化,一个阶段是后面的赋值,那么对应于,这种特殊写法而言,第一阶段的初始化,就发生在冒号后面的“re(r), im(i)”,而第二个阶段的赋值,就发生在最后面的“{}”进行,如果按照普通的写法,只是在"{}"中,进行设定,相当于放弃了第一个阶段的设置初始化的机会,虽然,最后,也可以起到将变量填值的效果,但从时间和效率上考虑,都没有直接在第一姐u但就把数值给设定进去高。

回想之前所记录的,class有两种经典的分类方式,一种带指针的,一种不带指针的,而这种就是不带指针的那种,并且,不带指针的类,大多数都是不需要写析构函数的!就比如这个例子。

创建对象的方式,有很多,下面展示了三种创建对象的方式:

 overloading(重载:函数可以有很多个)

在实际情况中,同样一个类,可不可以以多种的方式来创建呢?当然是可以的,那么C++实现这种需求的机制,就算重载(这种机制在C语言中是不被允许的!)

先看一组普通函数的重载操作,以上面的real函数为例,来进行重载操作,可以发现一个real函数是执行的返回操作,另一个real函数是执行的赋值操作,俩函数同名,那么既然两个函数的函数名一模一样,运行的时候如何区分呢?这就要站在编译器的角度去理解了,对于编译器而言,即便这俩函数名相同,但同名在进行编译的时候,还算会冠以不同的区分实际名称,通过这种方式来完成区分。站在程序员的角度看,是出现了两个同名的函数,但站在编译器的角度看,还是两个不同名的函数,应知对于编译器而言,是不能出现真正连实际名称都一样的函数的,否则会报错

再看一组构造函数的重载操作,就比如还是上图的Complex函数:

可以进行重载吗?答案是不可以!这是因为都包含有默认的参数,当编译器调用的时候:

无论调用那个,都好像"没问题",所以,编译器就无法区分到底去调用那个,导致"傻"掉了,所以,这种情况下,编译器,不允许进行重载,因为无法区分到底调用那个函数。这种重载出来的构造函数,就是与原来的构造函数是冲突的,是不能被编译器运行通过的!

 

(接看下篇博客)

类与函数的规范化写法(二)—HJ-record02

https://blog.csdn.net/qq_17846375/article/details/104530258

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值