从低到高Word格式.docx
《从低到高Word格式.docx》由会员分享,可在线阅读,更多相关《从低到高Word格式.docx(11页珍藏版)》请在冰豆网上搜索。
Tom.weight
也可以在访问的同时进行赋值Eg:
Tom.Weight=100;
要访问成员函数时,也是如此操作Eg:
Tom.GetWeight();
6.3.6不要给类赋值
Human.weight=100;
X因为人类是个抽象的名词,它泛指所有的人,所以不能给这个抽象的名词赋值,只能是用这个抽象的名词来具体化某一个人。
Tom.weight=100;
6.3.7对象只能调用类中存在的成员
注意一下几点:
1、要使用关键字class来声明一个类;
2、要使用类名来定义一个对象;
3、不要混淆声明和定义,声明时说明该类是什么,定义则是为一个对象分配内存
4、要使用点运算符访问对象的数据成员并给他们赋值
5、不要混淆类和对象,不要给类赋值
6.4公有
关键字public可以将类的成员说明为公有,即可以被该类的所有成员访问。
6.5私有
为什么要设置私有成员变量,然后用公有函数来访问它,这是为了提高代码的安全性,防止造成错误的输入和输出。
6.6成员函数的声明和定义
成员函数的定义只是在一般函数的定义的时候在函数名前加类名和冒号,其它保持不变。
voidHuman:
:
set(intw);
6.7为什么将成员函数的声明和定义分开
6.7.1普通内联函数
为了解决函数上百次的调用,可用关键字inline声明函数的,(Eg:
inlineintfunction());
则编译器将不会创建真正的函数,而只是将这个内联函数的所有代码复制到调用函数中,这样程序在执行调用行函数时就不需要回来跳转、自然就提高了程序运行时的效率,但会多一些代码,如果调用次数太多的话会增大程序的体积,如果函数很小,那么多次调用复制也不会增加许多体积,这时使用内联函数比较适合。
、
注意事项:
在不知道具体怎样操作时,最好先不要使用内联函数,等完成程序的大部分功能,再对符合要求的函数进行内联操作。
6.7.2成员内联函数
ClassA
Public:
Inlinevoidfunc(int,int)//将成员函数func()声明为内联函数
}
我们可以将成员函数的定义部分放到该类的声明中,也就是声明和定义合并在一起,Eg:
Voidfunc(intx,inty){i=x;
;
j=y;
这样该函数会自动成为内联函数。
6.8将类的声明和定义部分保存在头文件中
可以将该类的声明和定义保存在一个头文件中,一般扩展名为.hpp文件中。
#include*.hpp
*号是该文件取的名字,意思是将*.hpp文件读入cpp文件中。
6.9const成员函数
如果不想让某个成员函数修改成员变量的值,我们可以将这个成员函数声明为const
在编程时,一定要多用const,对于不应该改变成员函数,都应该声明为const,这样如果该成员函数试图修改该对象的成员变量时,编译器会提示错误,从而达到帮助勘察错的目的。
6.10构造函数
在创建某个类的对象是,由于该对象的状态(数据)不是很明确,因此需要对其进行初始化,
(略)
6.11默认构造函数
假如无法确定所要创建的长方形的长和宽,也就是说我们不提供构造函数,那么系统会自动创建一个构造函数,该函数没有参数,而且也不执行任何功能,它只用于构造一个对象。
rectangle(){}
一般来说,只要我们不创建任何构造函数,那么系统会为我们创建这个什么功能都没有的默认构造函数,而一旦我们创建了一个构造函数,则这个默认构造函数就会被自动屏蔽。
假如我们创建了代参数的构造函数后,又想要一个不带参数的构造函数,那么就必须自己再创建一个。
6.12析构函数
析构函数用于在对象呗销毁后清除它所占用的内存空间,也就是说它可以清除由构造函数创建的内存。
ClassA//声明一个类A
-A(){};
//类A的析构函数
};
一个类只能有一个析构函数,无论你以什么形式来重载析构函数,都会导致出错
每个对象在创建时都会自动调用该类的默认构造函数
程序结束时会调用该类的默认构造函数来释放该对象所占用的内存空间。
6.13析构对象数组
假如我们要声明许多对象,那么可以将这些对象放到一个数组里来声明。
Aa[3];
该语句声明了属于类A的对象数组a,它有3个对象成员,依次为a[0]、a[1]、a[2]。
C++第五版第六章函数和递归入门
使函数模块化的原因有:
1.分而治之法的使用,通过由小的、简单的部件构建程序。
2.软件重用性,一现有的函数作为构建模块来创建新的程序。
3.避免重复代码,此外,把程序分成有意义的函数也使其更容易调试和维护。
软件工程知识:
1、为了提高软件的可重用性,每个函数应该限定于单一的、良好定义的任务,并且函数名应该有效地表达任务,这样的函数才能是程序更易于编写、测试、调试和维护。
2、一个只执行单个任务的小函数的测试和调试要比一个执行多行的大函数的调试和测试要容易得多。
3、如果不能为函数起一个能表达其任务的简洁的名字,那么该函数很可能试图执行太多的不同任务,通常‘最好把这样的函数拆分成多个小函数。
6.3数学库函数(cmath)
有时,有些函数不是任何类的成员,这种函数称为全局函数,和类成员函数一样,全局函数的函数原型要放在头文件中,这样包含该头文件的任何程序就能重复使用这个全局函数。
一下列出了一些库函数:
函数描述
Ceil(X)X取整为不小于X的最小整数ceil(6.2)为7ceil(6.8)为6
Cos(X)X(X弧度)的余弦cos(0.0)为1.0
Fabs(X)X的绝对值fabs(0.0)为0.0
Exp(X)指函数e^x次方exp(1.0)为2.71828
Floor(X)X取整为不大于X的最大整数值floor(9.2)为9
Floor(9.8)为10.0
Fmod(x,y)x/y的浮点数的余数fmod(2.6,1.2)为1.0
Log(x)x(底数为10)的对数log10(100.0)为1.0
Pow(x,y)x的y次幂(x^y)pow(2,7)为128
Sin(x)x(弧度)的正弦sin(0.0)为0.0
Sqrt(x)x的平方根(其中x是一个非负值)sqrt(9.0)为3.0
Tan(x)x弧度的正切tan(0.0)为0
6.4多参数函数的定义
函数常常需要多条信息来执行它的任务,一次我们需多个参数的函数。
多个参数需要用逗号分隔列表的方式在原型和函数头中同时指定
6.5函数原型(函数声明)和实参类型的强制转化
函数签名:
函数原型的函数名和参数部分成为函数签名,或者成为签名。
函数签名并不指定函数的返回类型。
在同一作用域内的函数必须是独一无二的签名。
实参类型强制转换(argumentcoercion):
把参数的类型强制转换成函数原型中声明的形参类型。
如一个形参为double型的强制转换成int类型的函数原型。
6.6c++标准库文件
C++标准库分为很多个部分,每个部分都有自己的头文件。
头文件包含标准库的各个部分的相关函数类型。
头文件中还包含了这些寒素所需的各种类类型以及常量的定义。
头文件可以“指导”编译器怎样处理标准库和用户编写的组件好的接口问题。
C++标准库头文件说明
<
iostream>
它包含C++标准输入和输出函数的函数原型,并以取代了头文件<
iostream.h>
iomanip>
该头文件包含格式化数据流的流操作符的函数原型,已取代头文件
iomanip.h>
cmath>
该头文件包含数学库函数的函数原型,它取代了<
math.h>
cstdlib>
该头文件包含数转换为文本、文本转换为数、内存分配、随机数以及其他各种工具函数的函数原型,此头文件已经取代了<
stdlib.h>
ctime>
该头文件包含维护时间和日期的函数原型和类型。
它已经取代了<
time.h>
vector>
<
list>
<
deque>
queue>
,<
stack>
map>
.,<
set>
bitset>
这些头文件包含额实现C++标准库容器的类。
在执行程序期间,容器保存数据。
cctype>
该头文件包含测试字符特定属性(例如字符是否是数字字符或者标点符符号)的函数原型和用于将小写字母转换成大写字母,将大写字母转换成小写字母的函数原型。
它已经取代了头文件<
ctype.h>
cstring>
该头文件包含C式字符串处理函数的原型,它已经取代了头文件<
string.h>
typeinfo>
该头文件包含运行时类型识别(在执行确定数据类型)的类。
exception>
<
stdexcept>
这两个头文件包含用于异常处理的类。
memory>
该头文件包含被C++标准库用来C++标准用来向C++标准库容器分配内存的类和函数
fstream>
该头文件包含执行由磁盘文件输入和向磁盘文件输出的函数的函数原型。
fstream.h>
sting>
该文件包含来自C++标准的string类的定义
sstream>
该头文件包含了执行由内字符串输入和向内存字符输出的函数的函数原型
functional>
该头文件包含C++标准库算法所用的类和函数
iterator>
该头文件包含访问C++标准库容器中数据的类
algorithm>
该头文件包含访问C++标准库容器中数据数据的函数
cassert>
该文件包含辅助程序调试的添加诊断的宏。
它取代了旧版c++中的头文件<
assert.h>
cfloat>
该文件包含系统的浮点数长度限制,它已取代了头文件<
float.h>
climits>
该头文件包含系统的整数长度限制,它已经取代了头文件<
limits.h>
cstdio>
该头文件包含C式标准输入和输出库函数的函数原型以及这些函数所用的信息。
stdio.h>
locale>
该头文件包含一般流处理所用的类和函数,用来处理不同语言自然形式的数据(如:
货币格式、排序字符串、字符表示.......)
limits>
该头文件包含为各计算机平台定义数字数据类型限制的类。
utility>
该头文件包含被许多C++标准库头文件所用的类和函数。
错误预防技巧:
在switch语句中确定没有没有bug的情况那个下,我们也应该提供default的情况来处理错误
6.7随机数生成
一个骰子
为了生成0到5之间的整数型值,我们使用rand函数和取模运算符(%)如下:
Rand()%6
这种方法称为比例缩放(scaling)。
数字6称为比例缩放因子,我们可以对取模操作的结果加1来变换生成数字的范围(1~6)。
Rand函数实际上生成的是伪随机数。
重复调用rand会生成看似随机的数字序列。
然而,程序每次执行时产生的序列都是重复的。
为了在随机你时不用每次度输入种子哦,可以使用如下语句:
strand(time(0));
这条语句是计算机通过读取自己的时钟来获得种子值。
常见的编程错误:
在程序中多次调用srand函数会重启伪随机数字序列,并会影响rand生成的数字的随机性
比例缩放和偏移生成随机数的概括:
我们前面演示了通过一条简单的语句来模拟掷出六面骰子,语句如下
face=1+rand()%6;
该语句是将一个整数值(随机)赋给取值范围在1《=face《=6之间的变量face。
这一范围的宽度(即范围中连续整数的个数)是6,起始数字是1。
参照前面的语句,我们看到范围的宽度由用取模运算符对rand进行比例缩放的数(即6)决定,并且范围的起始数字等于添加到表达式rand中的数字(也就是1)。
规律概括如下:
B=A+rand()%C
B:
相当于所需的连续整数范围内的第一个数,C:
相当于所需的连续整数范围的宽度。
常见编程错误:
试图受用srand代替rand函数来生成随机数会导致编程错误,因为srand函数并没有返回值。
6.8实例研究:
博彩游戏和enum简介
博彩游戏中有一种为“掷双骰”的骰子游戏,游戏规则:
玩家掷出两个骰子。
,每个骰子有六面,分别含有1、2、3、4、5、6个点。
掷完骰子后,就计算两个朝上的面的点数之和。
如果首次掷出的点数和是7或者11,那么玩家赢;
如果首次投掷的点数之和是4、5、6、8、9、或者10,那么这个和就成为玩家的“点数”。
要想赢的话,玩家必须玩家必须连续掷骰子直到点数同这个目标为止。
即“得到了点数”。
但在得到点数前,如果掷到7,就会输掉。
良好的编程习惯:
1、作为用户自定义的类型的标识符其第一个字母最好是大写。
2、枚举常量的名字只有使用大写字母。
这样的话在程序中这些常量就会突出显示出来,并且可以提醒程序员这些枚举常量不是变量。
3、使用枚举而不是整型常量可以是程序更加、更易维护。
用户可以在声明枚举类型时一次性地设置枚举常量的值。
4、将等同于枚举常量的整数值赋给枚举类型的变量是一种编译以错误。
5、在枚举常量定义后,试图给枚举常量赋另外一个值将导致编译错误。
6.9存储类别
存储类别、作用域和链接:
标识符的作用域是指标识符在程序中可以被引用的范围。
有些标识符在整个程序中都应能被引用,有的只能限于在程序的某个部分引用。
标识符的连接决定了标识符只是在声明它的源文件中可以识别,还是在编译后连接在一起的多个文件中个可以识别。
标志符的存储类别说明符用于确定存储类别和连接。
存储类别有两种:
静态存储类别(static)和自动存储类别(auto)。
关键字auto和register可以用来声明自动存储类别的变量。
这样的变量在程序执行进入到定义它们的程序块时创建,在程序激活时存在,在程序执行退出时销毁。
局部变量:
只有函数中的局部变量可以是自动存储类别的。
函数的局部变量和参数在正常情况下是自动存储类别。
autodoublex;
默认情况下局部变量时自动存储类别,因此很少用关键字auto。
我们把自动存储类别的变量简称为自动变量。
常见的编译错误:
对一个标识符使用多个存储类别说明符会产生语法错误。
一个标识符只能用一个存储类别说明符。
关键字register只能与局部变量和函数参数一起使用。
性能提示:
Register常常是不必要的。
现在的优化编译器能够识别频繁使用的变量,并且不需要程序员进行register的声明就会自行决定吧这些变量存到寄存器中
静态存储类别:
关键字exterm和static用于给静态存储类别的变量声明标识符。
静态存储类别变量从程序执行开始处存在,然后一直存储在整个执行的过程中。
在程序开始执行时就为静态存储类别的变量分配空间。
当遇到这样的变量声明时,便对它们进行一次初始化。
对于静态存储类别的函数,和所有其他函数一样。
在程序执行开时函数名就可以存在。
然而,即便变量和函数在程序一开始执行时就存在,并不意味着这些标志符在整个程序中都能使用。
6.10作用域规则
当语句块是嵌套的并且外层语句块中的一个标识符和内层语句块中的一个标识符具有相同的名字时,外层语句块的标识符处于隐藏装填,直达内层语句块的执行结束为止。
常见的编译错误:
若不小心在内层语句块中使用了与外层语句块相同名字的标识符,而而程序眼事实上却希望外星语句块的标志符在内层语句块执行期间处于活动状态,通常将导致逻辑错误。
6.11函数调用堆栈和活动记录
堆栈的特性是先进后出。
每次函数调用另一个函数时,一个数据项会压到堆栈中。
这个数据项称为一个堆栈结构(stackframe)或者一条活动结构。
计算机的内存大小事有限的,因此只能有一定量的内存可用于保存函数调用堆栈的的活动记录。
如果太多的函数调用发生,以至于不能把相应的活动记录保存在堆栈中,那么就会发生堆栈溢出错误。
活动中的函数调用堆栈:
先把main函数压入堆栈中,再是其它函数,记住特性;
先进后出。
6.12无参数
C++ 中 ,空的参数列表可以通过在圆括号里面写上void 或者什么都不写
Voidprint();
可移植性提示:
C++中空函数参数列表的含义与C语言中的有很大不同,在C中,空的函数列表意味着不进行任何参数检查(即函数调用可以传递它想传递的任何参数);
在C++中,空的参数列表则意味着函数明确不需要任何参数,因此,使用该特性的C程序在C++中编译可能会引起编译错误。
6.14引用和引用参数
许多编程语言都有按值传递和按引用传递着两种函数参数传递方式。
当用按值传递的方式传递参数是,会(在函数调用堆栈上)产生一份实参值得副本,然后将副本传递给被调用的函数。
对副本的修改不影响调用者中原始变量的值。
这样就防止了对正确可靠的软件系统的开发产生很大阻碍的副作用。
性能提示:
按传值传递的一个缺点是,如果有一个大的数据项需要传递,那么复制这些数据需要花费很多时间和内存空间。
引用参数:
利用按引用传递,调用者使得被调用函数可以直接访问调用者的数据,并且如果被调用函数需要,还可以修改这些数据。
引用传递对性能很有帮组,可以消除按值传递赋值大量的数据开销。
软件工程知识:
按引用传递可能削弱安全性,因为被调用函数可能破坏调用者的数据。
引用参数是你函数调用中相应参数的别名。
为了指明一个函数参数是引用传递的,只要简单地在函数原型中参数类型后加一个&
标识符即可,在函数头部列出参数类型是也采用相同的做法。
int&
count读做“count是对一个int类型对象的引用”。
从函数返回引用:
函数可以返回引用,但是这种方法可能存在危险。
当返回一个在被调用函数中声明的变量的引用时,这个变量应该在函数中声明为static。
否则,该引用指的是在函数执行结束时被销毁的自动变量,这样的变量会被告知“未定义”并且程序的行为会不可预知。
对一个未定义的变量的引用称为虚悬引用(danglingreference)。
试图把已经声明的引用再作为另一个变量的别名是一种逻辑错误。
另一个变量的值只能给引用已是其别名的变量。
6.16一元作用域分辨运算符
当全局变量和局部变量声明为相同的名字。
需要用一元运算符(:
)来访问全局变量。
格式:
+变量名
试图使用一元作用域分辨运算符(:
)访问外层语句块中非全局变量时错误的。
总是使用一元作用域分辨运算符(:
)来引用全局变量会使得程序更容易阅读和理解。
6..17函数重载
C++允许定义多个具有相同名字的函数,只要这些函数的参数不同(至少参数类型或者参数数目或参数类型的顺序不同)。
这种特性称为函数重载(functionoverloading)。
当调用一个重载函数时,编译器会通过检查函数调用中的实参数目、类型和顺序来选择恰当的函数。
函数重载通常用于创建相似的任务、但是作用不同的数据类型的具有相同函数名字的多个参数。