第一篇:C和C++总结
1C中分为这几个存储区: 栈,堆,全局区(静态区)—静态变量,常量区
C++中分为这几个存储区:栈,堆(new创建,delete结束或者操作系统自动回收),全局区(静态区),自由存储区-(malloc创建,free结束),常量存储区,2看到一本书上写了进程通信方式有如下:
1)信号 ——软中断,2)管道
3)文件和记录锁定
4)消息队列
5)信号量
6)共享内存
Unix的启动顺序排序。
第一步:通过/boot/vm进行启动 linux内核
第二步:init /etc/inittab
第三步:启动相应的脚本,并且打开终端
rc.sysinit
rc.d(里面的脚本)
rc.local
第四步:启动login登录界面 login
第五步:在用户登录的时候执行sh脚本的顺序:每次登录的时候都会完全执行的/etc/profile.d/file
/etc/profile
/etc/bashrc
/root/.bashrc
/root/.bash_profile
Linux中查看目录大小的命令:du –sh filename
修改文件属性的命令是:chmod 777 file-R
切换为其他用户身份的命令是:du
第一次:第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
第二次:第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包
ACK(ack=k+1),此包发送完毕,客户端和服务器进入established状态,完成三次握手
指令用途
#空指令,无任何效果
#include包含一个源代码文件
#define定义宏
#undef取消已定义的宏
#if如果给定条件为真,则编译下面代码
#ifdef如果宏已经定义,则编译下面代码
#ifndef如果宏没有定义,则编译下面代码
#elif如果前面的#if给定条件不为真,当前条件为真,则编译下面代码
#endif结束一个#if……#else条件编译块
#error停止编译并显示错误信息
static全局变量与普通的全局变量有什么区别:static全局变量只初使化一次,防止在其他文件单元中被引用;
static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依据上一次结果值;
static函数与普通函数有什么区别:static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝
第二篇:c++知识点总结
C++知识点总结
Day01
一、名字空间(标准库中的标识符都定义在std名字空间中)
1、名字空间的定义
namespace 名字空间名{ 名字空间成员 }
2、名字空间指令
using namespace 名字空间名;
3、名字空间声明
using 名字空间名::标示符;
4、无名名字空间
namespace { 名字空间成员;}
5、无名名字空间的声明
::标示符
二、C++的结构、联合和枚举
1、C++的结构里面可以定义函数
2、C++里定义结构型变量的时候可以省略struct关键字
3、C++中的声明联合类型的变量可以不加union关键字,支持匿名联合
4、C++的枚举是一个独立的数据类型,而不是整数类型。
三、C++的bool类型
bool类型变量只可以取true或false
四、C++的函数
1、函数支持重载
重载:在同一个作用域中,函数名相同,参数表不同的函数之间构成重载关系。函数原型:返回类型+函数名+参数表
函数签名:函数名+参数表 //c++中,同一作用域中,函数签名必须是唯一的。
2、函数指针
函数指针的类型决定其具体指向的重载版本,而不是由实参的类型决定。
3、extern “C”
通过extern “C”指示编译器以C语言的方式处理C++源文件中的C函数(不做函数名置换)。
5、缺省参数
如果为函数的一个参数指定了缺省值,那么该参数右面的所有参数必须都有缺省值。注意:缺省参数只能用在函数的声明中。
6、哑元
借助哑元参数保证函数的向后兼容。借助哑元实现函数的重载。
7、内联
内联函数保持了函数的特性,同时避免了函数调用的开销。
inline关键字仅仅表示希望该函数被编译为内联,通常情况下,大函数和递归函数不会被处理为内联。
五、内存分配
1、new/delete操作符
如果内存是以数组的形式分配的,那么也应该按照数组的方式释放——delete[]。
如果new失败,这时会抛出bad_alloc异常,程序应该捕获并处理该异常,否则进程将被系统杀死。
Day02
一、引用&
1、引用实际上是一个变量的别名。
2、引用必须在声明的同时初始化
3、引用一旦初始化,再不能引用其他变量
4、只有const型引用才能引用常量
5、不能对常引用做赋值操作
二、C++中的类型转换
1、静态类型转换: static_cast<类型>(变量);需要编译器对类型转换安全性进行检查; 将void*转换为具体类型的指针。
在源类型和目标类型之间只要有一个方向上可以做隐式类型转换,那么在两个方向上就都可以做静态类型转换。
2、动态类型转换:dynamic_cast<类型>(变量);用于在具有多态特性的父子类之间的转换。
3、常量类型转换:const_cast<类型>(变量);去除指针或者引用上的const属性。
4、重解释类型转换:reinterpret_cast<类型>(变量);允许对任意类型的指针进行转换。在指针和整型之间进行转换。
三、类和对象
1、类的声明和定义可以分开、类的成员变量、类的成员函数。
2、类的访问控制
1)public:公有成员,谁都可以访问。
2)private:私有成员,只有自己才能访问。
3)protected:保护成员,只有自己和自己的子类可以访问
访控限定符
| 访控属性
| 自己
| 子类 | 其它--------------public
|
公有
|
Ok | Ok | Ok protected
|
保护
|
Ok | Ok | No private
|
私有
|
Ok | No | No 注意:类的缺省访控属性是私有,而结构体的缺省访控属性是公有。
3、构造函数
1)如果一个类中没有定义任何构造函数,系统就会自动提供一个默认的无参构造函数。2)如果为一个类定义了构造函数,系统就不会在为该类提供任何构造函数了。3)构造函数可以重载 4)构造函数初始化列表:
1>需要对类类型的成员变量做初始化; 2>含有引用或常量型成员;
4、对象的创建与销毁 1)在栈中创建对象
类名 对象名(构造参数);// 隐式构造
类名 对象名 = 类名(构造参数);// 显式构造 2)在栈中创建对象数组
类名 数组名[元素个数] = {类名(构造参数),...};3)在堆中创建对象
类名* 对象指针 = new 类名(构造参数);4)在堆中创建对象数组
类名* 对象数组指针 = new 类名[元素个数];Day03 类和对象(下)
一、this指针
1、一般而言,关键字this是一个指针。对于一般成员函数,它指向调用该成员函数的对象,而对于构造函数,它则指向这个正在被构造的对象。
2、在构造函数中可以通过this指针区分成员变量和局部变量(包括参数)。
3、基于this指针的自身引用还被用于支持多重串联调用的场合。
4、将this指针作为函数的参数,实现对象间的交互。
二、常量型成员函数和常量型对象
1、常量型成员函数中的this指针为常量型,以此防止对成员变量的意外修改。对常量型对象(包括指针和引用),只能调用其常量型成员函数。
2、被声明为mutable的成员变量可以在常量型成员函数中被修改。
3、常量型成员函数和具有相同签名的非常量型成员函数构成重载关系。
4、当常量型成员函数与非常量型成员函数构成重载关系时,非常量对象会优先选择非常量型成员函数。
三、析构函数
1、没有参数,不能重载。
构造顺序:创建成员变量->构造函数体 析构顺序:析构函数体->销毁成员变量
2、缺省析构函数
1>对于未定义析构函数的类,系统会提供缺省析构函数,该析构函数负责销毁该类的成员变量。
2>缺省析构函数不负责释放动态分配的资源。
3、对于动态分配的资源,必须通过自己定义的析构函数进行释放。
4、析构函数是释放的资源不仅限于内存资源。
四、拷贝构造函数
1、拷贝构造:用一个已有的对象去构造另一个同类型的副本对象。
2、拷贝构造是通过拷贝构造函数实现的。class 类名 {
类名(const 类名& 源对象引用){
从源对象到当前对象的复制;
} };
3、如果没有为一个类提供自定义的拷贝构造函数,系统就会提供一个缺省的拷贝构造函数,实现从源对象到目标对象的复制。
4、某些情况下系统提供的缺省拷贝构造函数可能无法满足具体的应用需求。这时就有必要提供自定义的拷贝构造函数。
5、拷贝构造发生的时机 1>构造对象副本;
2>以对象作为函数的参数和返回值; 3>以对象的方式捕获异常。
五、拷贝赋值运算符
1、拷贝赋值:用一个已有的对象赋值给另一个同类型的副本对象。
2、拷贝赋值是通过拷贝赋值函数实现的。class 类名 {
类名& operator=(const 类名& 源对象引用){
从源对象到当前对象的复制;
} };
3、如果没有为一个类提供自定义的拷贝赋值函数,系统就会提供一个缺省的拷贝赋值函数,实现从源对象到目标对象的复制。
4、某些情况下系统提供的缺省拷贝赋值函数可能无法满足具体的应用需求。这时就有必要提供自定义的拷贝赋值函数。
六、静态成员
1、静态成员是属于类的,唯一的,可为该类对象所共享。
2、静态成员函数只能访问静态成员。
3、非静态成员函数既能访问静态成员,也能访问非静态成员。
4、静态成员变量必须在类外定义并初始化。
5、既可以通过类也可以通过对象访问静态成员,但最好通过类。
6、静态成员同样受类的访问控制属性的影响。
Day04
一、指向成员变量的指针
1、定义语法:成员变量类型 类名::*指针变量名;string Student::*pstrName;//pstrName是指向Student类中string类型的成员变量的指针
2、赋值即初始化语法:指针变量名= &类名::成员变量名;pstrName = &Student::m_strName;// pstrName指向Student类的m_strName成员变量
3、解引用语法:对象.*指针变量名 或者 对象指针->*指针变量名 Student student(...);cout << student.*pstrName << endl;Student* pStudent = &student;cout << pStudent->*pstrName << endl;
二、指向成员函数的指针
1、定义语法:成员函数返回类型(类名::*指针变量名)(形参表);void(Student::*pfuncSetName)(const string&);
2、赋值和初始化语法:指针变量名 = &类名::成员函数名;pfuncSetName = &Student::SetName;
3、解引用语法:(对象.*指针变量名)(...)、(对象指针->*指针变量名)(...)Student student(...);//创建对象(student.*puncSetName)(...);Student* pStudent = &student;//创建对象指针(pStudent->*pfuncSetName)(...);
三、对于静态成员,可以使用普通指针访问,不需要成员指针。
四、操作符重载
1、操作符的通用语法
1)双目操作符:<左操作数><操作符><右操作数>,L#R。
2)单目操作符:<操作数><操作符>或<操作符><操作数>,O#或#O
2、被重载操作符的操作数中至少有一个是类类型。
3、重载操作符不会改变优先级。
4、重载操作符无法改变操作数的个数。
5、除“()”以外所有操作符函数都不能含有缺省参数。
6、所谓重载操作符实际上就是定一个提供操作符运算法则的函数(成员函数或全局函数)。
五、双目操作符重载
L#R 全局函数:operator#(L, R),如果需要可定义为友元。成员函数:L.operator#(R)
六、单目操作符重载
#O 全局函数:operator#(O)成员函数:O.opertor#()取负运算“-“
七、输入输出操作符重载
一般情况下,输入输出操作符比较适合通过全局(友元)函数来实现,避免修改标准C++库的iostream类。
重载输出运算符函数形式:
ostream& operator<<(ostream& os, const 类名& 对象引用){
输出对象的内容;
return os;} 重载输出运算符函数形式:
istream& operator>>(istream& is, 类名& 对象引用){
输入对象的内容;
return is;}
八、不允许重载的操作符
::
-作用域解析.取字节数 typeid针对键盘设备的输入流对象针对显示器设备的输出流对象针对出错设备的输出流对象-stderr
3、文本I/O 1)文本文件的格式化I/O 2)文件位置
A.get和put位置 B.随机读写 3)非格式化I/O
4、二进制I/O
第三篇:C、C++总结
1、类:类是一种抽象的数据结构,用来描述对象的属性,是将不同数据类型的数据以及与这些数据相关的操作封装在一起的集合体。(封装性)
一个类的对象所占空间的大小由它的数据成员所占据的空间总和决定;当类有virtual函数时,再加上4个字节的大小。
2、面向过程与面向对象程序设计的不同:
(1)过程是基于算法的,而对象是基于类的;
(2)过程是以函数(过程)的设计来实现的,而对象是以类的设计来实现的;
(3)过程通过数据流图(流程图)来体现的,而对象是通过类图(用例图)来体现的;(4)过程需要将步骤一步一步的具体化,而对象则只注重类的设计,不管实现方法。
3、面向对象的四大特点:抽象、封装、继承、多态
4、访问控制权限:
(1)public公有型:外部可以访问
(2)protected 保护型:除了本类、子类与友元可访问外其它的都不能访问(3)private 私有型:除了本类外,外部的都不能访问
5、类与对象的区别:
(1)二者的定义不同:类是不同类型数据及其相关操作的集合,对象则是类的实例化(2)类是个类型,不占空间,但对象占空间。
(3)类是类型而不是数据对象,每个类的对象都是该类数据成员的拷贝
6、继承与派生的目的:(1)实现代码的重用
(2)使已存在的类不需修改地适应新应用 7.继承的特点:
(1)每个派生类代表基类的特定版本
(2)基类的属性和方法,派生类必须拥有(构造与析构不会被继承)8.继承的3种方式:public,private,protected
9、多态:是指发出同样的消息被不同类型的对象接收后导致完全不同的行为(1)多态的条件:
○1有两个是父子关系的类 ○2有同名的虚函数
○3有父类指针或引用调用子类对象(2)多态的实现:
函数的重载 运算符重载 虚函数
1、static有什么用途?(请至少说明两种)关键字static的作用是什么?
定义静态变量 1.限制变量的作用域 2.设置变量的存储域
C和C++中static用法(1)C中:
○1当一个变量被定义成static型时,表明该变量是一个静态变量,存储在静态存储区中,只能被定义初始化一次;特别的当全局变量被定义成static型时,还表明该变量不能被外部文件所引用
○2当一个函数被声明为static型时,表明该函数是一个静态函数,不能被外部文件所调用
1(2)C++的类中:
○1当类的数据成员被声明为static型时,表明该成员是一个能被所有对象共享的数据成员,不与任何具体对象挂勾
○2 当类的成员函数被声明为static型时,表明该成员是静态成员函数。
2、引用与指针有什么区别? 1)引用必须被初始化,指针不必。
2)引用初始化以后不能被改变,指针可以改变所指的对象。2)不存在指向空值的引用,但是存在指向空值的指针。
3、描述实时系统的基本特性
在特定时间内完成特定的任务,实时性与可靠性
4、全局变量和局部变量在内存中是否有区别?如果有,是什么区别? 全局变量储存在静态数据库,局部变量在堆栈 5 什么是平衡二叉树?
左右子树都是平衡二叉树 且左右子树的深度差值的绝对值不大于1
6、堆栈溢出一般是由什么原因导致的? 没有回收垃圾资源
7、什么函数不能声明为虚函数? constructor 8 冒泡排序算法的时间复杂度是什么? O(n^2)
9、Internet采用哪种网络协议?该协议的主要层次结构? tcp/ip 应用层/传输层/网络层/数据链路层
10、Internet物理地址和IP地址转换采用什么协议? ARP(Address Resolution Protocol)(地址解析協議)
11、.IP地址的编码分为哪俩部分?
IP地址由两部分组成,网络号和主机号。不过是要和“子网掩码”按位与上之后才能区分哪些是网络位哪些是主机位。
12、分别给出BOOL,int,float,指针变量 与“零值”比较的 if 语句(假设变量名为var)
BOOL型变量:if(!var)int型变量: if(var==0)float型变量:
const float EPSINON = 0.00001;
if((x >=-EPSINON)&&(x <= EPSINON)
指针变量:
if(var==NULL)
13、不能做switch()的参数类型是: switch的参数不能为实型/
14、局部变量能否和全局变量重名?
答:能,局部会屏蔽全局。要用全局变量,需要使用“::” /
15、如何引用一个已经定义过的全局变量? 答:extern
16、全局变量可不可以定义在可被多个.C文件包含的头文件中?为什么? 答:可以,在不同的C文件中以static形式来声明同名全局变量。
17、语句for(;1 ;)有什么问题?它是什么意思?
答:和while(1)相同。
18、do„„while和while„„do有什么区别?
答:前一个循环一遍再判断,后一个判断以后再循环
18、static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?
static全局变量与普通的全局变量有什么区别:static全局变量只初使化一次,防止在其他文件单元中被引用;static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依据上一次结果值;
static函数与普通函数有什么区别:static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝。
程序的局部变量存在于(堆栈)中,全局变量存在于(静态区)中,动态申请数据存在于(堆)中。
19、sizeof(...)是运算符,它的功能是:获得保证能容纳实现所建立的最大对象的字节大小;strlen(...)是函数,要在运行时才能计算。参数必须是字符型指针(char*)。它的功能是:返回字符串的长度。20、队列和栈有什么区别? 队列先进先出,栈后进先出
21、在c语言库函数中将一个字符转换成整型的函数是atool()吗,这个函数的原型是什么?
函数名: atol 功 能: 把字符串转换成长整型数
用 法: long atol(const char *nptr);
22、对于一个频繁使用的短小函数,在C语言中应用什么实现,在C++中应用什么实现? c用宏定义,c++用inline
25、直接链接两个信令点的一组链路称作什么? PPP点到点连接
26、软件测试都有那些种类? 黑盒:针对系统功能的测试
白合:测试函数功能,各函数接口
27.确定模块的功能和模块的接口是在软件设计的那个队段完成的? 概要设计阶段
28/TCP/IP通信建立的过程怎样,端口有什么作用? 三次握手,确定是哪个应用程序使用该协议 29/进程和线程的差别。
线程是指进程内的一个执行单元,也是进程内的可调度实体.与进程的区别:(1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位
(2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行
(3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源.(4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。30、测试方法
人工测试:个人复查、抽查和会审
机器测试:黑盒测试和白盒测试
31、Heap与stack的差别。Heap是堆,stack是栈。
Stack的空间由操作系统自动分配/释放,Heap上的空间手动分配/释放。Stack空间有限,Heap是很大的自由存储区
C中的malloc函数分配的内存空间即在堆上,C++中对应的是new操作符。
1、软件测试(英语:software testing),描述一种用来促进鉴定软件的正确性、完整性、安全性和质量的过程。换句话说,软件测试是一种实际输出与预期输出间的审核或者比较过程。软件测试的经典定义是:在规定的条件下对程序进行操作,以发现程序错误,衡量软件质量,并对其是否能满足设计要求进行评估的过程。流程:1.软件测试流程 :需求了解--测试计划--测试设计--测试用例编写--测试执行--bug管理跟踪--测试报告生成
2.bug就是测试过程中发现的程序缺陷,可以指需求上的,也可以指功能、性能上的
3.bug提交有多种方式,可以通过测试管理工具来管理bug,比如QC等 4.bug的生命周期: 发现bug(open)--修复bug(fixed)--关闭bug(closed)4.软件测试方法:是指测试软件性能的方法。包括有:白盒测试、黑盒测试、动态测试(单元测试、集成测试、系统测试、验收测试、回归测试等。)
5.测试工具:三类软件测试工具: Mercury测试工具,Rational测试工具,Segue测试工具,qtp自动化测试工具和AutoRunner工具
6.测试内容:负载压力、功能测试、白盒测试、测试管理、测试辅助。
2、算法(Algorithm)是一系列解决问题的清晰指令,即能够对一定规范的输入,在有限时间内获得所要求的输出。图像处理算法工程师
1、一个算法的优劣可以用空间复杂度与时间复杂度来衡量。
2、一个算法应该具有以下五个重要的特征: 有穷性、确定性、输入、输出、可行性。
3、冒泡排序(BubbleSort)一次比较两个元素,如果他们的顺序错误就把他们交换过来。基本概念是:依次比较相邻的两个数,将小数放在前面,大数放在后面。即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。此第一趟结束,将最大的数放到了最后。在第二趟:仍从第一对数开始比较(因为可能由于第2个数和第3个数的交换,使得第1个数不再小于第2个数),将小数放前,大数放后,一直比较到倒数第二个数(倒数第一的位置上已经是最大的),第二趟结束,在倒数第二的位置上得到一个新的最大数(其实在整个数列中是第二大的数)。如此下去,重复以上过程,直至最终完成排序。由于在排序过程中总是小数往前放,大数往后放,相当于气泡往上升,所以称作冒泡排序。
4快速排序:基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
算法的时间复杂度是一个函数,它定量描述了该算法的运行时间。一个程序的空间复杂度是指运行完一个程序所需内存的大小。
第四篇:c++课程设计总结
课程设计总结
经过一个学期对《C++程序设计》的学习,我学习到了基本的理论知识,了解到了C++语言程序设计的思想,这些知识都为我的课程实践和进一步的学习打下了坚实的基础。在为期近两周的C++课程设计中,我体会颇多,学到了很多东西。我加强了对C++程序设计这门课程的认识,并且复习了自己以前学习到的知识。这些都使得我对计算机语言的学习有了更深入的认识!总之,通过这次课程设计,我收获颇丰,相信会为自己以后的学习和工作带来很大的好处。像职工信息表这样的程序设计,经历了平时在课堂和考试中不会出现的问题和考验。而这些问题,这并不是我们平时只靠课本,就可以轻易解决的。所以,锻炼了我们挑战难题,学会用已掌握的知识去解决具体问题的能力,进一步培养了独立思考问题和解决问题的能力。特别是学会了在Visual C++中如何调试程序的方法。当然,老师的指导和同学的帮助也是不可忽视的,他们给了我许多提示和帮助,教会了我编译复杂程序的方法。
在老师和同学的帮助下,通过自己的努力,终于完成了这次职工信息表的简单课程设计。我经过这段时间的编程,对其中的艰辛,我是深有体会。从刚开始的选择程序、理解程序到后来的调试程序以及改进程序这个过程中,我遇到了各种各样的困难和挫折。但是我坚定信念,对自己充满了信心,想尽一切办法克服重重困难。
通过课程设计的训练,我进一步学习和掌握了对程序的设计和编写,从中体会到了面向对象程序设计的方便和巧妙。懂得了在进行编写一个程序之前,要有明确的目标和整体的设计思想。另外某些具体的细节内容也是相当的重要。这些宝贵的编程思想和从中摸索到的经验都是在编程的过程中获得的宝贵财富。这些经验对我以后的编程会有很大的帮助的,我要好好利用。
虽然这次课程设计是在参考程序的基础之上进行的,但是我觉得对自己是一个挑战和锻炼。我很欣慰自己能在程序中加入自己的想法和有关程序内容,也就是对它的程序改进了一番改进,并有创新。但是我感觉自己的创新还不够典型,总之还不是很满意。另外由于时间的紧迫和对知识的了解不够广泛,造成了系统中还存在许多不足,功能上还不够完善。以后我会继续努力,大胆创新,争取能编写出透射着自己思想的程序。这次课程设计让我充分认识到了自己的不足,认识到了动手能力的重要性。我会在以后的学习中更加努力锻炼自己,提高自己,让自己写出更好更完善的程序,为以后的编程打好基础!
总而言之,这次C++程序设计实践让我收获很大。
计算机科学与技术13-2班
2010年7月4日
第五篇:C++程序设计总结
第一章面向对象编程原理
近五十年间,软件技术经历了多个阶段的发展演变 目前为止最流行的技术还是面向过程编程(POP)
面向过程编程采用了自顶向下的设计方案,问题被看做多个执行任务的序列。为完成这些任务,须实现一些函数。
面向过程有两大不足,即:(1)数据可在程序内自由迁移,程序内任何函数都会引起数据的更改,增加了数据的脆弱性。(2)它并不能很好地建模现实世界。
为了克服面向过程编程中的不足,人们发明了面向对象编程(OOP)。它采用自底向上的编程方案,在程序开发中,把数据视为重要元素,不允许数据在系统内自由迁移。它还将数据和函数紧密绑定于成为类的数据结构中,函数可操作类中的数据。此特性称为数据封装。
在面向对象编程中,问题被视为一系列称为对象的实体的集合。对象是类的实例; 将数据与程序的直接访问隔绝,这称为数据隐藏。
数据抽象指的是,将各种必要特性合并,而不引入背景细节。 继承是这样的一个过程,即某类的对象得到另一类对象的属性。
多态指的是,一个名称,多种形态。在程序中,我们可以借此定义多个同名函数。此特性亦可重载运算符,这样一来,同一个运算符在不同的实例下,会有不同的行为。 动态绑定指的是,给定过程的代码,直到运行期被调用时才确定。 消息传递涉及对象名,函数(消息)名以及发送的信息。
与传统的编程技术相比,面向对象技术具有诸多优势——最显著的当属重用技术。 在实时系统等几乎所有的计算机领域,面向对象编程的应用程序都已受到重视。 不少语言都支持面向对象编程,流行的语言包括C++、Smalltalk和Java。
第二章C++入门
C++是C语言的超级
C++在C语言的基础上,添加了一些面向对象的特性,诸如对象、继承、函数重载和运算符重载。这些特性加强了程序的清晰性,可扩展性,使程序容易维护。
C++可用于开发各种系统,诸如编辑器、编译器、数据库、通信系统以及其他更多复杂的实际系统。
C++支持交互式输入输出,并引入了新的注释符号//,可用于注释单句。它也支持C语言的注释风格。
和C程序一样,所有C++程序的执行入口都是main()函数,并以return()语句作为结束。头文件iostream应包含于所有使用输入输出操作的程序开头。 所有标准C++程序都要包含using namespace std指令
典型的C++程序包括四个基本部分:也就是头文件包含部分、类声明部分、成员函数部分和主程序部分
和C程序一样,C++程序可用于任何文本编辑器创建
大多数编译器提供了集成开发运行环境。流行的编译器系统有UNIX AT&T C++、Turbo C++和微软公司的Visual C++
第三章符号、表达式和控制结构
C++有不同的符号,包括关键字、标识符、常量、字符串和操作符 标识符指的是变量名、函数名、数组名、类名等 C++中增加了void的一个用途,可用于声明通用指针
C++中枚举数据类型略有不同,枚举类型名称为新的类型名。这样我们就可以声明枚举类型的变量
在C++中,字符数组的大小应比字符串的实际长度大1 C++增加了指针常量和常量指针的概念,对于前者我们不能修改赋予它的地址值,对于后者,我们不能修改它指向的内容。
在C++的内存管理和多态实现中,指针被广泛地使用。
C++中提供了const修饰符,用于声明常量,常量也是变量,只是其值不可变更。const修饰符默认修饰整型。
C++的变量类型检查非常严格,它不允许不同类型变量之间的赋值。类型转换是打破此规的唯一办法。
C++允许我们在程序中随处声明变量,而且可以利用声明处的表达式,在运行期完成初始化。
引用变量给之前定义的变量提供了一个别名。它们都指向内存中的同一个数据对象。所以,改变其中一个的值,另一边量的值也会随之改变。
引用变量必须在声明时初始化,这建立了它和要引用的变量之间的对应关系。 作用于解析操作符(::)的主要用于类,以识别成员函数所属的类
除了malloc()、calloc()、free()函数外,C++提供了两个一元操作符,即new和delete,以更好和更方便地分配和释放内存
C++也提供了操纵器,来格式化输出数据。最常用的操纵器为endl和setw C++支持七种表达式类型。表达式中数据类型混用时,C++使用特定规则,自动地进行类型转换。
使用类型转换操作符,C++也可显示地进行变量和表达式的类型转换
和C语言一样,C++也支持三种基本的控制结构,也就是顺序结构,分支结构和循环结构,并使用各种控制语句实现它们,比如if、if…else、switch、do…while、while以及for。
第四章C++中的函数
在程序的不同处,调用函数可减少程序的大小。
在C++中,main()函数向操作系统返回一个整型值。因为函数的返回值类型默认是整型,所以main()函数中的关键字int是可选的。而如果没有返回语句,大部分C++编译器会提示一个警告。
函数原型向编译器提供了函数的细节,比如参数的数目和类型,以及返回值的类型。 C++的引用变量使我们可以传引用参数给函数。函数也可以返回引用变量。
当函数声明为内联时,编译器用相应的函数代码替换了函数调用。一般情况下,小函数才使用内联。
编译器可能会忽略函数的内联声明,如果函数声明太长或过于复杂,编译器将按常规函数编译它。
当函数声明时,C++允许我们把默认值赋给函数参数。这种情况下,我们可以无需指明所有参数,便可调用函数。默认参数总是由右到左添加。 C++中,函数的参数可声明为常量,表示函数不可更改此变量。
C++允许函数重载,也就是说,我们可以定义多个同名函数。通过检查参数数目和类型编译器会准确地匹配函数调用和函数代码。
C++支持两种新的函数类型,亦即友元函数和虚函数。
C++标准库支持很多数学库函数,使用它们可以完成许多数学计算。
第五章 类和对象
类是结构体数据类型的扩展,一个类有多个成员变量和成员函数。 默认情况下,类的成员是私有的,而结构体的成员是公用的。
只有成员函数可以访问私有数据成员和私有函数。但是类外可以访问公用成员。 在C++中,类变量称为对象。利用对象并使用点操作符,我们可以访问类的公用成员。 我们可以在类内或类外定义成员函数。成员函数和常规函数的区别在于,成员函数的头
部有一个隶属标识符,以表明所属类。
对象声明时,内存空间才会分配。每一对象的成员变量空间单独分配,而成员函数的空间则统一分配。
类的一个成员变量可声明为静态成员,一般用于维护整个类的通用值。 静态成员变量必须定义于类外。
静态成员函数可访问声明在同类的静态成员,调用静态成员函数时需要用到类名。 C++允许我们使用对象数组。 对象可用作函数自变量。
友元函数不在友元声明类的作用域类,它可以访问累的所有私有数据。 函数可以返回对象。
如果成员函数不改变类内的任何数据,我们可以将其声明为常量成员函数,只要在函数原型中加上关键词const(声明和定义都要加)。
我们也可以在函数内定义和使用类。这种类称为局部类。
第六章构造函数和析构函数
C++提供了一种称为构造函数的特殊成员函数,它能帮助对象在创建时完成初始化。这一过程被称为对象的自动初始化。 构造函数名和类名一致。
构造函数通常用来初始化变量,以及分配内存。 和常规函数一样,构造函数也可以被重载。
当对象同时被创建和初始化时,复制构造函数被调用。 我们可以声明一个常量对象,其数据值不能改变。
C++还提供另一种成员函数,称为析构函数。当对象不再需要时,会调用这种函数来销毁对象。
第七章运算符重载和类型转换
运算符重载是C++的重要特性之一。又被称为编译时多态性。
使用重载特性,我们可以对两个用户自定义数据类型,比如说对象,执行相加的操作,使用的语法就和基本数据类型一样。
我们可以重载几乎所有C++的运算符,下面几个是例外:
类成员访问符(.,.*)。 作用域解析符(::)。
大小运算符(sizeof)。 条件运算符(?:)。
运算符重载是通过一种称为运算符函数的特殊函数完成的,该函数定义了运算符的特定任务。
运算符重载时有一些限制。运算符函数必须是非静态的成员函数或者友元函数。重载的运算符必须有至少一个用户自定义类型的操作数。
编译器不支持用户自定义数据类型的自动类型转换,我们可以使用自定义的转换运算符函数,以实现自定义数据类型的自动类型转换。 转换运算符函数应符合下列条件:
必须是类成员。 必须不指定返回值。 必须没有参数。
第八章继承:类的扩展
从旧类派生一个新类的机制被称为继承。继承提供了可重用性的概念。通过继承,C++的类可以被重用。
派生类继承了基类的一部分或所有特性。 只有一个基类的派生类被称为单继承。 可从多个类继承,这被称为多继承。 可从另一派生类继承类,这被称为多级继承。
当某类的属性被多于一个类继承时,这被称为层次继承。 不管是在公用模式还是私有模式,类的私有成员都不可被继承。
以公用模式继承的保护成员仍为派生类的保护成员,而以私有模式继承的保护成员,则变成派生类的私有成员。
友元函数和友元类的成员函数可直接访问私有和保护数据。
派生类的成员函数只能直接访问保护和公用数据。不过他们可通过基类的成员函数访问私有数据。
多路继承可能引起祖父基类的继承成员的重复。通过将共同的基类设为虚基类,我们可以避免祖父基类成员的重复。
在多继承中,基类的创建次序与他们在派生类中的声明次序一致。 类可包含其他类的对象。这被称为包含关系或嵌套。