linux环境程序设计教学第12章语言编程基础_第1页
linux环境程序设计教学第12章语言编程基础_第2页
linux环境程序设计教学第12章语言编程基础_第3页
linux环境程序设计教学第12章语言编程基础_第4页
linux环境程序设计教学第12章语言编程基础_第5页
已阅读5页,还剩16页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第12章C++语言编程基础C++程序设计语言可以看作C语言的改进和升级,不仅完全兼容C语言的语法和函数库,还引入了面向对象、运算符重载、多态性、数据流和模板等最新的编程思想。极大地保证了源代码的生产率、质量和可

重用性。GNU项目为Linux系统上C++开发提供了G++编译器,GDB调试器也能用来调式C++程序。本章简单讲解C++语言的特性与基本用法。12.1

类和数据抽象类和数据抽象是面向对象思想的基本范畴,面向对象思想将任何事物看作对象,对象有自己的属性和行为,收集这些属性就是数据抽象的任务。例如将篮球看作一个对象,篮球的属性有重量、颜色、内部气体压力等属性,重量和内部气体压力的差异决定篮球的弹性行为的不同,对篮球充气和放气的行为又能改变将篮球的内部气体压力属性,将这些属性作为分析篮球对象行为的数据,就是对篮球的数据抽象。如果把同一类事物的属性和行为作为一个类别来认识,这个类别就是该类事物的类,每一个有相同属性和行为的事物都是该类的对象。12.1.1

用类实现数据抽象在C++语言中,类是封装的程序包。程序包里有自身的数据和函数,这些数据可看作属性,函数可看作是行为。对象是由类在源代码中生成出来独立的程序体,对象具有类的全部属性和行为。因此可以认为,对象是有“生命”的程序体,它能通过行为改变自己的属性,也能根据属性产生不同的行为。以联系人信息为例,它的属性有联系人名称、电话和地址,它的行为是修改联系人信息、输出联系人信息,那么我们可以将联系人信息设计成类。源代码如下:class

Buddy

{//定义类名称public://以下是公共成员Buddy();//构造函数void

setBuddy(const

char

*,

long,

const

char

*);//修改联系人信息函数void

printBuddy();

//输出联系人信息函数private://以下是私有成员//电话号码//地址char

name[50];//联系人姓名long

telnum;char

address[200];};12.1.1

用类实现数据抽象代码定义了一个名为Buddy的类,Buddy类有6个成员。public和

private称为成员访问说明符。public说明符下的成员可以在该类以外被访问,而private说明符下的成员只能在该类内被访问。public说明符下有3个函数,与类同名的函数称为构造函数,它可以自动对类的成员进行初始化,setBuddy()函数和printBuddy()函数的作用是修改和输出联系人的信息。private说明符下有两个数组和一个变量,简单地说,这些数据只能被该类中的函数访问。这种做法很好地保护了数据的独立性,外界只能通过类的行为来改变类的属性。(12_1_1.c)该例中使用了名字空间,using

std::cout的作用是将cout操作符从标准名字空间std中提取出来。每一个类都有名字空间,Buddy类的名字空间就是Buddy,所以在定义Buddy的成员函数时,要使用完整的名字空间Buddy::setBuddy()。在主函数中,Buddy类生成出对象b,对象b就具备了Buddy类的全部特性,但又保持了独立的数据空间。直接访问b对象内private成员是非法的,所以只能使用

public成员来访问private成员。假如buddy类生成出另一个c对象,那么c对象与b对象也是相互独立的,具备各自的结构。12.1.2

类作用域和访问类成员//类成员函数//参数名telnum与类成员telnum重名类的作用域是整个文件,类的成员数据和成员函数的作用域在该类之中。类的所有成员函数在类的内部都可以直接访问其它类成员,并且可以按名称引用。在成员函数中定义的变量,作用域是该函数。如果成员函数定义了与类成员具有相同名称的数据,要访问同名的类成员需要加入作用域解析运算符(::)。如下例所示:class

Buddy{

//定义类名称long

telnum;

//类中的变量};Buddy::setTelnum(long

telnum){Buddy::telnum

=

telnum;}代码中成员函数setTelnum()的参数与类成员变量名称相同,访问时使用域解析运算符,这样两个变量都能使用。12.1.3

从实现中分离接口良好的软件工程习惯要求接口与实现分离。这种方式使程序的修改更为容易,正如使用类的程序所关心,只要类的接口没有变化,对类内部的改变不会影响程序的其它部分。例如联系人信息类的定义,可以放在两个文件中。(1)类的接口buddy.h:(2)类的实现buddy.cpp:类的接口应在设计时尽量考虑周全,避免过于频繁的改动。当程序需要使用该类时,只用在程序文件中包含类的接口文件。12.1.4

控制访问成员成员访问说明符共有3个,分别是public、private和

protected。public说明符表示该成员可以在该类以外被访问,这种成员通常是作为类的接口函数或数据。

private说明符表示该成员只能被该类的其它成员访问,这样类的数据可以得到保护。protected说明符表示该

成员可以被该类和该类的子类所访问,在类的继承时需要用到该概念。类成员的默认访问模式是private,因此类定义的开始到第一个成员访问说明符之间的所有成员都是private成员。在每个成员访问说明符之后,由该成员说明符所调用的模式将在下一个成员访问说明符或者类定义结束之前保持有效。成员访问说明符可以重复,但通常将同一类成员放在一起说明,这样可避免混淆。12.1.5

构造函数和析构函数所有的类都可定义一个或多个构造函数和析构函数。构造函数是与类同名的函数,构造函数的作用是在对象生成时初始化成员数据。C++语言规定,每个类必须有构造函数,如果没有为该类定义构造函数,那么编译器会自动加上一个没有参数的默认构造函数,默认构造函数不会对类成员数据进行初始化。构造函数的另一作用是在生成对象的同时初始化类成员数据,如下例所示://使用该函数的参数初始化类成员数据strcpy(name,

n);telnum

=

t;strcpy(address,

a);class

Buddy{public:Buddy(const

char*n,long

t,const

char*a)

//有参数的构造函数};void

Buddy::Buddy(const

char

*n,long

t,const

char

*a)

//定义构造函数{}//生成该对象的同时初始化成员数据//调用对象自身的函数输出数据int

main(){Buddy

b("Tom",

1234567890,

"China");b.printBuddy();}析构函数的作用是在对象结束时清理对象的成员数据。析构函数的名称是在类的名称前加上一个“~”符号。如果在类中使用了动态内存分配,那么就可以使用析构函数在对象结束时释放该内存空间。12.1.6

const对象和const成员函数const修饰符的作用是声明常量型的变量,修改const类型的数据将引起编译错误。对象也可以被定义为const类型,这样该对象内的数据就不能再修改。如下例所示:const

Buddy

b("Tom",

1234567890,

"China");//生成常量对象b.setBuddy("Jerry",

4567890123,

"USA");//该语句是非法的当对象b被定义为const类型后,任何途径对成员数据的修改都是非法的。C++语言还规定,只有被定义为const类型的成员函数才能访问const类型对象的数据。即使成员函数Buddy::printBuddy()不会修改该对象的数据,也被拒绝访问。所以,当对象被当作

const类型使用时,需要用到的成员函数必须定义为const类型,如下例所示:void

Buddy::printBuddy()

const;

//定义const类型成员函数12.1.7 friend对象和friend类friend被称作友元。类的friend函数并不是该类的成员函数,但被定义为该类的友元后,friend函数可以访问类的private成员。定义friend函数需要在类的定义说明,如下例所示://使用名字空间std中的cin//定义类名称//将inputBuddy()定义为Buddy类的友元};//将输入的值保存在Buddy类的成员中void

inputBuddy(Buddy&b){cout<<"姓名:"<<endl;cin.getline(,

50);cout<<"地址:"<<endl;cin.getline(b.address,

200);cout<<"电话:"<<endl;cin>>b.telnum;}using

std::cin;class

Buddy

{friend

void

inputBuddy(Buddy

&);//使用友元为对象b的成员赋值//输出对象b的成员数据intmain(){Buddy

b;//生成对象binputBuddy(b);b.printBuddy();}friend函数引用的参数是类的地址,通过类的地址就可以访问该类的成员。这一用法与指针的原理是相似的。类也可以作为另一个类的友元,例如Class2类作为Class1类的友元,那么需要在Class1类的定义中将Class2类定义为友元。如下例所示:友元关系是授予的而不是获取的,也就是说Class1必须授予Class2为友元。而且,友元关系是不对称的,也不能传递。如果Class2是Class1的友元,Class3又是Class2的友元,不能推出Class3是Class1友元的结论。12.1.8

this指针this指针是类定义中指向自身的指针,每个对象都可以通过this指针来访问它自己的地址。对象的this指针并

不是对象本身的组成部分,它不占用对象的内存空间。在每次非static成员函数调用对象的时候,this指针作为隐藏的第一个参数由编译器传递给对象。this指针隐含地引用对象的成员数据和成员函数,也就是说,在成员函数的定义中,引用的每个成员前都有一个this指针。this指针也可以显式地使用,如下例所示:void

Buddy::cpObjaddress(const

char

*cp){cp=;

//使用this指针引用成员数据}12.1.9

动态内存分配在C语言中,动态分配内存可使用malloc()和free()函数,这种分配方式必须指定分配内存空间的长度。C++语言提供了new和delete运算符执行动态内存分配,这种分配方式优于C语言的分配方式,申请内存一般形式是:指针名=new

数据类型;释放内存的形式为:delete指针名;如下例所示:Buddy

*p

=

new

Buddy;if

(p

!=

NULL)delete

p;//动态分配内存空间//判断动态内存分配操作是否成功//释放内存空间该代码使用动态内存分配方式创建了Buddy类的对象,指针*p指向该内存空间。当该对象不再使用时,使用delete语句释放内存空间。这种方式使对象的使用更为灵活,new操作符会为对象自动申请适合其大小的空间。如果动态内存分配操作成功,new表达式的返回值是该内存空间的首地址,否则将返回NULL指针。12.1.10

static类成员在C语言中static修饰符用来定义静态数据类型,如果将类成员数据定义为static类型,那么该类生成的所有对象将使用同一个内存空间保存该成员数据。//定义类名称//公共成员//构造函数//输出联系人信息函数//私有成员//静态成员数据//定义构造函数private:static

int

count;};Buddy::Buddy(){count++;//改变静态成员数据}void

Buddy::printCount();

//定义输出联系人总数函数{cout<<"联系人总数为:"<<count<<endl;class

Buddy

{public:Buddy

();void

printCount();}//使用类Buddy生成了3个对象//输出联系人的总数//输出联系人的总数//输出联系人的总数intmain(){Buddy

a,

b,c;a.printCount();b.printCount();c.printCount();return

0;}该程序中3条输出结果是相同的,因为这3个对象中的数据成员count共享一个内存空间。程序运行时,每个对象在内存中都会获得类的所有成员数据的一个副本,static成员数据则是在编译时就划分了。12.2 C++特性12.1节简单介绍了C++语言的类和数据抽

象,这只是C++语言作为面向对象语言的

基本特性。除此以外,运算符重载、继承、虚拟函数和多态性、流输入与输出、模板、异常处理都是C++语言的重要特性。本节

将讲解对这些特性的概要。12.2.1

运算符重载在C++语言的定义中,很多运算符只能对简单的数据结构进行操作。(12_2_1.cpp)该例使用的是C语言中的字符串处理函数,以便于读者理解操作符重载的工作过程。程序的开始为字符串设计了类,重载的运算符被定义为该类的一个成员函数,字符串相加在重载运算符函数中实现。主函数中执行的操作“s1+s2”实际上等同于

s1.operator+(s2),重载运算符的作用是简

化了此函数的表达方式。12.2.2

继承面向对象编程的一个重要特性是继承,继承是指利用一个类生成另一个类的对象,前者称为父类,后者称为子类。子类不但获得了父类的所有成员,还可以加上它自己的一些成员。例如,矩形和三角形都有属性底和高,那么可以利用它们之间的共同特点定义出父类Cstd,再让矩形类Crect和三角形类Cdelt继承父类Cstd。(12_2_2.c)在程序中,类Crect和类Cdelt的每一个对象都包含类Cstd的成员width、height和set_values()。标识符protected与private类似,它们的唯一区别是父类的protected成员可以被子类的其它成员所使用,然而private成员就不可以。12.2.3

虚拟函数和多态性虚拟函数是一种特殊的成员,该成员在父类中定义但不实现该函数的细节,而将细节留在子类中进行实现。虚拟函数必须加上关键字virtual,以便可以使用指针对指向相应的对象进行操作。多态性是通过虚拟函数实现的,即通过同一父类的虚拟函数,子类实现不同的细节。代码如下://定义虚拟函数class

Cstd{public:virtual

int

area

(void)

{

return

(0);}void

set_values

(int

a,

int

b)

{

width=a;

height=b;}protected:int

width;//图形的底int

height;//图形的高};class

Crect:public

Cstd{

//定义子类Crectpublic:int

area

(void)

{return

(width

*

height);}//实现父类虚拟函数的细节};类Cstd的成员函数area()被说明为虚拟函数,该函数没有任何参数。子类Crect继承自父类Cstd,定义时实现了虚拟函数的细节。如果还有其它子类,这些子类也可以重新定义虚拟函数的细节,彼此独立。12.2.4

流输入与输出C++输入与输出操作是通过控制数据流实现的,流是数据的字节序列。在输入操作中,数据从输入设备流向内存;输出操作中,数据从内存流向输出设备。C++提供了流输入输出函数库,函数库的名称是iostream。该函数库将流输入输出定义为操作符>>和<<,前者的作用是输入,后者的作用是输出。另外它在标准名字空间std中定义了cin、cout和endl函数,由此可见操作符>>和<<是通过在这3个函数中的重载而实现的。cin函数的作用是输入数据流,cout的作用是输出数据流,endl函数的作用是立即将缓存中的数据全部输出,如下例所示:01#include

<iostream>//包含流输入输出函数库02using

namespace

std;//使用std名字空间03int

main()04{05int

a;//声明整型变量a06cin

>>

a;//输入数据到变量a07cout

<<

a

<<

endl;//将变量a的数据输出08return

0;09}源代码中首先包含了函数库文件,与C语言不同的是,C++语言的函数库没有“.h”后缀名。主函数内声明了整型变量a,其后使用cin函数和“>>”操作符从终端读取用户的输入到变量a。然后用cout函数和“<<”

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论