版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
移动应用软件开发技术
第二讲:C++编程基础《移动应用软件开发技术》课程建设小组北京大学二零一一年*致谢:感谢Intel对本课程项目的支持
移动应用软件开发技术
第二讲:C++编程基础C++编程基础C++编程基础3C++标识符(Identifiers)程序设计语言中为变量、常量、类型、函数等取的名字称为标识符。标识符由大小写字母、数字和下划线组成,并且只能以字母或下划线开始。
例如:
9abc、*abc是不合法的标识符注意:标识符区分大小写标识符长度任意提倡使用“见名知义”的标识符避免使用系统已定义的标识符(系统保留字)3C++标识符(Identifiers)4关键字关键字在计算机中有预定的含义。关键字又称保留字,它们不能再被用户重新定义使用。
autoboolbreakcasecatchcharclassconstconst_castcontinuedefaultdeletedodoubleelseenumexplicitexternfalsefloatforfriendgotoifinlineintlongmutablenamespacenewoperatorprivateprotectedpublicregisterreturnshortsignedsizeofstaticstructswitchtemplatethisthrowtruetrytypedeftypeidtypenameunionunsignedusingvirtualvoidvolatilewhile4关键字5注释符C++语言保留了C语言中以/*开始,*/结束的注释,这种方式适用于多行的注释同时C++语言中还提供行注释符//,该注释在它的行结束处结束,适用于短注释。5注释符6数据类型数据类型是不同形式的信息在内存中分配方式的基本约定(不同类型的数据在内存中占用的字节数有所不同),是构造程序的基础。常量、变量甚至函数都具有自己的数据类型。类型名说明符整型int字符型char浮点型float布尔型bool空值型void五种基本数据类型6数据类型数据类型是不同形式的信息在内存中分配方式的基本约定7类型名字宽(字节)范围short[int]2–32768~32767signedshort[int]2–32768~32767unsignedshort[int]20~65535int4–2147483648~2147483647signed[int]4–2147483648~2147483647unsigned[int]40~4294967295long[int]4–2147483648~2147483647signedlong[int]4–2147483648~2147483647unsignedlong[int]40~4294967295char1–128~127signedchar1–128~127unsignedchar10~255float4double8longdouble8void032位机上各基本类型的字宽及表示范围7类型名字宽(字节)范围short[int]2–327688变量变量是在程序执行过程中,其值可以改变的量;变量有3个基本要素:名字类型值8变量变量是在程序执行过程中,其值可以改变的量;9变量的名字是一种标识符,需用遵守标识符的规则区分大小写mycarMyCarMYCAR是三个变量名称不能使用关键字作为变量名“见名知意”常见命名方法:my_bookmyBookiMyBook9变量的名字是一种标识符,需用遵守标识符的规则10变量的类型C++中的变量在使用前必须定义,定义变量时必须指明变量的类型及名字。变量的类型包含数据类型和存储类型定义或说明变量的格式:<类型说明符><变量名表>;例如:staticintmy_car;10变量的类型C++中的变量在使用前必须定义,定义变量时必须11变量的值变量自身包含两个值:变量值:变量所表示的数据值地址值:变量在内存中的地址值变量可以在定义时初始化,给变量赋一个初值。
例如:inta=3,b=-78;doublearea=67.34;变量赋值,或更改变量值 例如:a=5;取变量地址值:通过“&”运算符来获得 例如:&a;11变量的值变量自身包含两个值:12C++提供另一种形式的初始化方法。例如,前面两个语句可改写为:
inta(3),b(-78);doublearea(67.34);12C++提供另一种形式的初始化方法。例如,前面两个语句可改13常量的定义格式定义格式:
const<类型说明符><常量名>=<常量值>
例如:
constdoublepi=3.141592653;13常量的定义格式定义格式:14整型常量十进制整型常量由0~9的数字组成,不能以0开头,没前缀例如:20189等八进制整型常量由0~7的数字组成,以0位前缀例如:032024等十六进制整型常量由0~9及a~f字母组成,0x或0X为前缀例如:0x1a0X3F等长整型常量后缀L(l),无符号整型常量后缀U(u)例如:123L12322U223212ul14整型常量十进制整型常量15字符串常量以一对双撇号括起来的字符序列例如:“Helloworld!\n”字符串常量中可以包含空格符、转义字符及其他字符,也可以包含汉字。由于双撇号是字符串的定界符,因此字符串中使用\”表示双撇号。字符串中字符的个数可以为任意数目字符串常量后面有一个结束符’\0’“a”与’a’不同15字符串常量以一对双撇号括起来的字符序列16运算符
运算符是指用来表示在数据上执行某些特定操作的符号。参与运算的数据称为操作数。(可以分别称为单目、双目和三目运算符)。算术运算符关系运算符逻辑运算符位操作运算符赋值运算符其他运算符16运算符运算符是指用来表示在数据17
逻辑运算真值表(真为非0,假为0)aba&&ba||b!a!b0000110非00110非000101非0非0110017逻辑运算真值表(真为非0,假为0)aba&&ba|18位操作运算符位运算符是对其操作数按其二进制形式逐位进行运算,参加位运算的操作数必须为整数。C++中所有的位运算符如下:~(按位求反) <<(左移)>>(右移) &(按位与) ^(按位异或) |(按位或)18位操作运算符位运算符是对其操作数按其二进制形式逐位进行运19选择语句利用选择语句可以实现具有选择结构的程序选择语句有两种条件语句(if语句)开关语句(switch语句)特点:具有一定的判断功能可以根据给定的条件来决定执行哪路分支中的语句19选择语句利用选择语句可以实现具有选择结构的程序20C++中有三种循环语句可用来实现循环结构:while语句、do_while语句和for语句。这些语句各有各的特点,而且常常可以互相替代。在编程时应根据需要选择最适合的循环语句。循环语句20循环语句21转向语句goto无条件转向语句,很少使用break退出语句continue结束本次循环语句转向语句用于改变语句的执行顺序21转向语句goto无条件转向语句,很少使用22枚举的定义枚举类型和枚举变量的定义格式如下,其中enum是枚举类型定义的关键字。enum枚举类型名{
枚举常量名1, 枚举常量名2,
…}枚举变量;//在定义枚举类型的同时定义枚举变量。例如:enumWeekDay{ Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday}today;也可在枚举类型定义后再定义枚举变量,格式如下:枚举类型名枚举变量。如:WeekDaytomorrow;22枚举的定义23枚举类型voidmain(){ enumWeakDay{ Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday}; WeakDayToday; Today=Friday; cout<<"Today="<<Today<<endl; Today=Sunday; cout<<"Today="<<Today<<endl;}Today=5Today=023枚举类型voidmain()Today=524756-2354……107a[0]a[1]a[2]a[n-1]图一维数组数组是一些意义上相关的同类型变量的有序集合。每个数组元素都是一个变量,用来存放不同的值。数组元素引用形式:数组名[下标]数组24756-2354……107a[0]a[指针的概念1.指针:即变量的内存地址。2.指针变量指针变量是一种特殊的变量:
它存放的不是数据的值,而是另一个变量的地址。指针变量常常直接简称为指针。
指针指针的概念
指针26一个指针在定义以后,并不具体地指向某个变量,而只是确定了类型。可以对指针进行初始化,让它指向某个具体的变量。
“&”是取地址运算符,用在一个存储器操作数的前面,表示取存储器操作数的地址值。例如:
floatsalary;float*salary_ptr=&salary;就将指针salary_ptr初始化为变量salary的地址值,也即指向了具体的salary。
26一个指针在定义以后,并不具体地指向某个变量,而只是确定了27指针的赋值和引用
除了在指针定义时对它进行初始化外,还可以使用赋值运算来给指针赋以变量的地址值。例如:
inta=-8978;int*p;p=&a;这里,p被赋值为变量a的地址。也可以将一个已被赋值的指针赋给另一个相同类型的指针。例如:
doublea;double*x=&a,*y;y=x;这样一来,y就与x指向同一个变量a。27指针的赋值和引用28一个关于指针的例子。
#include<iostream.h>voidmain(){intx=50;int*x_ptr=&x;//x_ptr指向xcout<<"x="<<x<<endl;//输出x的值
cout<<"*x_ptr="<<*x_ptr<<endl; //输出x_ptr所指单元的值
cout<<"x_ptr="<<x_ptr<<endl; //输出x_ptr的值*x_ptr=100;cout<<"x="<<x<<endl;cout<<"*x_ptr="<<*x_ptr<<endl;cout<<"x_ptr="<<x_ptr<<endl;}程序的输出为:
x=50*x_ptr=50x_ptr=0x0065FDF4x=100*x_ptr=100x_ptr=0x0065FDF428一个关于指针的例子。程序的输出为:29指针与整数进行的加、减运算,代表着指针在内存空间上、下移动。具体上移或下移的字节数与其类型密切相关。例如,假设在某字长为32的计算机中,一个int型数据占4个字节,如果有
inta=78;int*x=&a;x初始化为指向变量a。在语句
x=x+1;执行后,x中存放的地址值被加了4,指向变量a下面一个整数。同理,语句
x=x–1;执行后,x指向了上一个整数。指针运算29指针与整数进行的加、减运算,代表着指针在内存空间上、下移30
当++或––与*同时作用于指针时,同样应该注意运算的顺序。 例如:x=*p++;相当于x=*(p++);即先从当前地址中取值,然后将指针指向下一个数据。 又如:x=*++p;相当于x=*(++p);先将地址加1,再取地址中的数据赋给x。 而x=++*p;相当于x=++(*p);表示先取p所指向的单元内的数据值,再将数据值加1后赋给x。30 当++或––与*同时作用于指针时,同样应该注意运算的31例:给出程序的运行结果#include<iostream.h>voidmain(){ inta[3]={24,30,8}; int*p; p=a; intx; x=*p++; cout<<x<<","<<*p<<endl; x=*++p; cout<<x<<","<<*p<<endl; x=++*p; cout<<x<<","<<*p<<endl;}24,308,89,93132函数定义与函数原型C++中的函数由一段相对独立的程序组成,这段程序能实现某一方面独立和完整的功能。例
求5!+4!#include<iostream.h>intfactorial(intn){ intz,i; z=1; for(i=1;i<=n;i++) z=z*i; returnz;}voidmain(){ intx; x=factorial(5)+factorial(4); cout<<”5!+4!=”<<x<<endl;}程序运行结果:5!+4!=14432函数定义与函数原型C++中的函数由一段相对独立的程序组成(1)形式参数:在被调用函数名后面的()内的变量称为形式参数(简称“形参”)。(2)实际参数:在调用函数名后面的()内中的表达式或变量称为实际参数(简称实参)。
例
求从键盘上输入的两数中的最大值#include<iostream.h>voidmax(intx,inty);voidmain(){ inta,b; cout<<"Pleaseinputtwointegers:"; cin>>a>>b; max(a,b);}voidmax(intx,inty){ intw; w=x>y?x:y; cout<<"Thebigoneoftwoinputnumberis:"<<w<<endl;}运行结果:Pleaseinputtwointegers:54
-89Thebigoneoftwoinputnumberis:54
程序中x,y为形参,a,b为实参。(1)形式参数:在被调用函数名后面的()内的变量称为形式34函数的传值调用例
交换两个整数变量的值。#include<iostream.h>voidexch(intx,inty){ intz; z=x; x=y; y=z;}voidmain(){ inta=3,b=5; exch(a,b); cout<<"a="<<a<<",b="<<b<<endl;}//运行结果:a=3,b=5变量a,b的值没有改变。34函数的传值调用voidmain()//运行结果:a=335函数的传址调用
传址调用:指针作函数参数例
交换两个整数变量的值。#include<iostream.h>voidexch(int*x,int*y){ intz; z=*x; *x=*y; *y=z;}voidmain(){ inta=3,b=5; exch(&a,&b); cout<<"a="<<a<<",b="<<b<<endl;}//运行结果:a=5,b=3变量a,b的值已经交换。35函数的传址调用
传址调用:指针作函数参36动态内存分配
在ANSIC中,malloc()和free()
C++兼容了C语言中的这两个函数,并提供了两个新的操作符:new和deleteC++程序运行时可以在内存区使用new运算符和delete运算符动态创建和删除变量。36动态内存分配在ANSIC中,mallo37//动态分配#include"stdio.h“
//包含标准输入输出头文件#include"stdlib.h" //包含动态存储分配函数头文件voidmain(){ int*p; //定义一个整型指针p
//为指针p动态分配一个存储单元
p=(int*)malloc(sizeof(int)); *p=6; //将6赋给指针p指向的存储单元 printf("%d",*p);
free(p);
//释放p所指向的存储单元}37//动态分配38例内存动态分配程序#include<iostream.h>voidmain(){ int*pc; cout<<"pc="<<pc<<endl;
pc=newint; cout<<"pc="<<pc<<endl; *pc=10; cout<<"pc="<<pc<<endl; cout<<"*pc="<<*pc<<endl;
deletepc;}堆0pc38例内存动态分配程序堆0pc39对于数组进行动态分配的格式为:指针变量名=new类型名[下标表达式];delete[]指向该数组的指针变量名;两式中的方括号是非常重要的,两者必须配对使用,如果delete语句中少了方括号,因编译器认为该指针是指向数组第一个元素的指针,会产生回收不彻底的问题(只回收了第一个元素所占空间),加了方括号后就转化为指向数组的指针,回收整个数组。delete[]的方括号中不需要填数组元素数,系统自知。即使写了,编译器也忽略。请注意“下标表达式”不是常量表达式,即它的值不必在编译时确定,可以在运行时确定。39对于数组进行动态分配的格式为:40【例】动态数组的建立与撤销#include<iostream.h>#include<string.h>voidmain(){ intn; char*pc; cout<<"请输入动态数组的元素个数"<<endl;
cin>>n;
//在运行时确定,可输入17
pc=newchar[n];
//申请17个字符(可装8个汉字和一个结束符)的内存空间
strcpy(pc,"堆内存的动态分配"); cout<<pc<<endl;
delete[]pc;//释放pc所指向的n个字符的内存空间}40【例】动态数组的建立与撤销41结构定义格式:struct结构名{
类型1结构成员1; 类型2结构成员2;
…;};例如:structTeacher{ longintid; charname[10];
intage; intsex;};结构定义后,可以声明结构变量或指向结构的指针如:
TeacherZhang;
Teacher*tp; tp=newTeacher;41结构定义格式:例如:结构定义后,可以声明结构变量或指向结42类类是具有相同属性和行为的一组对象的集合,它为属于该类的全部对象提供了统一的抽象描述,其内部包括属性和行为两个主要部分。利用类可以实现数据的封装、隐藏、继承与派生。利用类易于编写大型复杂程序,其模块化程度比C中采用函数更高。42类类是具有相同属性和行为的一组对象的集合,它为属于该类的43类的定义分为说明和实现两个部分。类说明部分是用来声明该类中的成员。类的成员包括数据成员和函数成员。其中,函数成员又称成员函数或“方法”,用于对数据成员进行各种操作。类实现部分用来对成员函数进行定义。即说明部分告诉类要“干什么”,实现部分告诉类“怎么干”。43类的定义分为说明和实现两个部分。44类说明部分类说明部分一般格式如下:class类名{
private:(或缺省时)
数据成员声明或函数成员的原型;
protected:
数据成员声明或函数成员的原型;
public:
数据成员声明或函数成员的原型;};44类说明部分类说明部分一般格式如下:45类实现部分
类的实现部分,包括所有在类体中说明的成员函数的定义。成员函数的定义通常在类定义体之外给出,其中每个成员函数定义格式为:返回值类型类名::成员函数名(<参数表>){
…//函数体}
类的成员函数在类外部定义时,前面必须加上“类名::”,以说明所定义的函数是哪一个类的成员。“::”称为作用域运算符。45类实现部分类的实现部分,包括所有在类体中说明的成46
封装性来自对类成员的访问控制权限。在C++中,类的成员从访问权限上分为私有(private)、公有(public)和保护(protected)三类。私有成员通常是一些数据成员。private权限为类带来了封装性,它使私有成员隐藏起来,不能从类的外部对它们进行访问,或者说它们从类外部是不可见的,只有类自己的成员函数才可以访问它们。公有成员往往是一些操作(即成员函数),可在程序中类的外部访问它们,它们是类的对外接口。类封装和数据隐藏46封装性来自对类成员的访问控制权限。类封装和数据隐藏47例:点类Point的定义classPoint{private:
doublex,y;public:
voidSetPoint(doublex,doubley); doubleGetX();
doubleGetY(); voidPrint();};voidPoint::SetPoint(doublea,doubleb)//定义成员函数SetPoint(){x=a; y=b;}doublePoint::GetX()//定义成员函数GetX(){returnx;}doublePoint::GetY()//定义成员函数GetY(){returny;}voidPoint::Print()//定义成员函数Print(){cout<<”X=”<<x<<”,”<<“Y=”<<y<<endl;}类实现部分:类说明部分:47例:点类Point的定义classPoint{vo48
定义类时说明部分中的关键字public、private、protected从它们出现的位置起开始生效,直到出现另一个访问权限关键字为止。访问权限关键字可以按任意顺序出现任意次,但是,如果把所有的私有成员和公有成员归类放在一起,能增强程序的可读性。如果把所有的私有成员放在公有成员前面,可以自动获得缺省访问控制权限private。4849
类中的数据成员可以是任何数据类型。例如整型、浮点型、字符型、数组、指针和引用等。
不能在类的说明部分给类的数据成员赋初值,例如在点类的定义中,下面的定义是错的:classPoint{
intx=0,y=0; public: ┆};49类中的数据成员可以是任何数据类型。例如整型、浮点50对象的定义和成员表示
类描述了对象的数据存储和操作特性,对象是类的实例。正像定义int类型的变量一样,创建类类型Point的对象也被看作定义Point类型的变量。对象在它的类确定了以后,定义格式为:
类名<对象名表>
例如,定义(或者说创建)两个点类Point的对象:
Point p1,p2(2.0,3.0);<对象名表>中,可以是一般的对象名,也可以是指向对象的指针或对象的引用,还可以是对象数组名。例如,一个复数类Complex的对象可以如下定义:
Complexc1,c2,*pc,c[10];
50对象的定义和成员表示类描述了对象51对象成员的表示方法
一个对象的成员就是该对象的类所定义的成员。对象成员有数据成员和成员函数。
一般对象的成员表示如下:
<对象名>.<成员名>
或者
<对象名>.<成员名>(<参数表>)
前者用来表示数据成员,后者用来表示成员函数。这里的“.”是一个运算符,该运算符的功能是表示对象的成员。
指向对象的指针的成员表示如下:
<对象指针名>-><成员名>
或者
<对象指针名>-><成员名>(<参数表>)
这里的“->”是一个表示成员的运算符,它与“.”运算符的区别是“->”用来表示对象的指针的成员,而“.”用来表示一般对象的成员。同样,前者表示数据成员,而后者表示成员函数。
51对象成员的表示方法52#include<iostream.h>#include"cdate.h"voidmain(){CDatedate1,date2;date1.SetDate(1996,5,4);date2.SetDate(1998,4,9);intleap=date1.IsLeapYear();cout<<leap<<endl;date1.Print();date2.Print();}例分析该程序的输出结果classCDate{public:voidSetDate(inty,intm,intd);intIsLeapYear();voidPrint();private:intyear,month,day;};voidCDate::SetDate(inty,intm,intd){year=y;month=m;day=d;}intCDate::IsLeapYear(){return(year%4==0&&year%100!=0)||(year%400==0);}voidCDate::Print(){cout<<year<<"."<<month<<"."<<day<<endl;}52#include<iostream.h>例分析该程53构造函数与析构函数构造函数和析构函数是在类体中说明的两种特殊的成员函数。构造函数的功能是在创建对象时,用给定的对象对对象进行初始化。析构函数的功能是用来释放一个对象,它与构造函数的功能正好相反。53构造函数与析构函数构造函数和析构函数是在类体中说明的两种54构造函数的特点如下:构造函数是成员函数,函数体可写在类体内,也可写在类体外。构造函数是一个特殊的成员函数,该函数的名字与类名相同,该函数不指定类型说明。该函数可以没有参数,也可有参数。构造函数可以重载,即可定义多个参数个数不同的函数。程序中一般不直接调用构造函数,在创建对象时系统自动调用构造函数。54构造函数的特点如下:55构造函数举例classClock{public: Clock(intNewH,intNewM,intNewS);//构造函数
voidSetTime(intNewH,intNewM,intNewS); voidShowTime();private: intHour,Minute,Second;};55构造函数举例classClock56构造函数的实现:Clock::Clock(intNewH,intNewM,intNewS){ Hour=NewH; Minute=NewM; Second=NewS;}建立对象时构造函数的作用:voidmain(){
Clockc(0,0,0);//隐含调用构造函数,将初始值作为实参。
c.ShowTime();}3156构造函数的实现:3157析构函数完成对象被删除前的一些清理工作。在对象的生存期结束的时刻系统自动调用它,然后再释放此对象所属的空间。如果程序中未声明析构函数,编译器将自动产生一个默认的析构函数。57析构函数完成对象被删除前的一些清理工作。58构造函数和析构函数举例#include<iostream>usingnamespacestd;classPoint{public:
Point(intxx,intyy);
~Point();//...其它函数原形
private:intX,intY;};58构造函数和析构函数举例#include<iostream59Point::Point(intxx,intyy){X=xx;Y=yy;}Point::~Point(){}//...其它函数的实现略4159Point::Point(intxx,intyy)460继承是C++实现软件重用的主要手段。计程车公共汽车旅游车汽车客车货车工程车
交通工具类层次关系图60继承是C++实现软件重用的主要手段。计程车公共汽车旅游61派生(Derivate)类的定义格式派生类的定义格式为:class派生类名:继承方式基类名{ //派生类新增成员定义
…};
“继承方式”用于规定派生类中由基类继承到的那部分成员在派生类中的访问控制权限。继承方式用下述三个关键字之一来指定:public:公有继承;protected:保护继承;private:私有继承。61派生(Derivate)类的定义格式派生类的定义格式为:62继承方式基类特性派生类特性Public继承publicpublicprotectedprotectedprivate不可访问Private继承publicprivateprotectedprivateprivate不可访问Protected继承publicprotectedprotectedprotectedprivate不可访问62继承方式基类特性派生类特性Publicpublicpub63class<派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…{
<派生类新定义成员>};多继承与单继承的区别从定义格式上看,主要是多继承的基类多于一个。63class<派生类名>:<继承方式1><基类名1>,<64
派生类构造函数的一般格式如下:
<派生类名>(<派生类构造函数总参数表>):<基类构造函数>(参数表1),<子对象名>(<参数表2>)
{
<派生类中数据成员初始化>
};
派生类构造函数的调用顺序如下:
·
基类的构造函数
·
子对象类的构造函数(如果有的话)
·
派生类构造函数
执行的顺序是:先祖先(基类),再客人(成员对象),后自己(派生类)
。64派生类构造函数的一般格式如下:
<派生类名>(<派生类65派生类构造函数实例#include<iostream.h>classA{ //定义基类private: inta;public:A(intx){a=x;cout<<"A'sconstructorcalled."<<endl;}voidshow(){cout<<a<<endl;}};classB{ //定义另一个类private: intb;public:B(intx){b=x;cout<<"B'sconstructorcalled."<<endl;}intget(){returnb;}};65派生类构造函数实例66派生类构造函数实例classC:publicA{ //定义派生类private: intc; Bobj_b;public: C(intx,inty,intz):A(x),obj_b(y)//派生类构造函数
{ c=z; cout<<"C'sconstructorcalled."<<endl; } voidshow(){ A::show(); cout<<obj_b.get()<<","<<c<<endl; }};voidmain(){ Cc1(1,2,5),c2(3,4,7); c1.show(); c2.show();}程序输出如下:A'sconstructorcalled.B'sconstructorcalled.C'sconstructorcalled.A'sconstructorcalled.B'sconstructorcalled.C'sconstructorcalled.12,534,766派生类构造函数实例classC:publicA67派生类析构函数实例#include<iostream.h>classX{ intx1,x2;public: X(inti,intj){x1=i;x2=j;} voidprint(){cout<<x1<<”,”<<x2<<endl;} ~X(){cout<<”X’sdestructorcalled.”<<endl;}};classY:publicX{ inty; //派生类Y新增数据成员public: Y(inti,intj,intk):X(i,j) {y=k;} //派生类构造函数
voidprint(){X::print();cout<<y<<endl;} ~Y(){cout<<”Y’sdestructorcalled.”<<endl;}};voidmain(){Yy1(5,6,7),y2(2,3,4);y1.print();y2.print();}程序输出结果如下:5,672,34Y’sdestructorcalled.X’sdestructorcalled.Y’sdestructorcalled.X’sdestructorcalled.67派生类析构函数实例#include<iostream.h68A{a}A{a}B1{b1}B2{b2}C{c,f1(),f2(),print()}A::aB1::b1A::aB2::b2C::c重复继承关系及其内存映象(a)(b)在上例中若声明:Cc1;则对继承的数据成员a的访问 c1.a;或 c1.A::a;都会出现二义性。系统将没有足够的信息区分是访问B1中的a,还是B2中的a。派生类C的对象c1中保存了间接基类A的成员a的两份拷贝。为避免出现这种二义性,可以用作用域运算符::加以限定。例如:c1.B1::a;c1.B2::a;要想从根本上消除这种二义性,应想法使这个公共基类在间接派生类中只产生一个该公共基类的子对象。这就需要将这个公共基类定义为虚基类。重复继承及其二义性68A{a}A{a}B1{b1}B2{b2}C{c69
虚基类与普通基类的区别只有在发生重复继承时才能表现出来:被重复继承的基类被说明为虚基类后,其成员在派生类中只产生一个唯一的副本,这就从根本上解决了二义性问题。
虚基类的说明是在派生类的定义中进行,其说明的语法格式如下:class派生类名:virtual继承方式基类名}…;}其中,virtual是说明虚基类的关键字。虚基类的说明是在定义派生类时,写在派生类名的后面。6970虚基类的说明classA{protected: inta;public: A(); voidf();};classB1:virtualpublicA{protected: intb1;};classB2:virtualpublicA{protected: intb2;};classc:publicB1,publicB2{private: intc;public: C(); intg();}A{f(),a}B1{b1}B2{b2}C{g(),c}含有虚基类时的类层次关系图70虚基类的说明classAclassc:publi71函数重载的区分机制1.用参数区分函数重载的不同调用版本重载函数靠参数不同而区分不同调用版本。决定参数是否相同有参数个数、参数类型等要素。如length()函数的重载说明:intlength(intx);intlength(intx,inty);doublelength(doublex1,doublex2,doubley1,doubley2);这三个函数,由于它们的函数名相同,参数不同而成为重载函数,与它们返回值类型相同并无关系。intsum(intx,inty);和doublesum(inta,intb);这两个函数不是重载函数,因为它们参数个数和类型都相同,尽管它们的返回值类型不同、形式参数名也不同。编译程序认为它们是对一个函数的重新定义(override)另外不同的参数传递方式也无法区分重载函数,如:intfunc1(intvalue);intfunc1(int&value);不能作为重载函数。
71函数重载的区分机制1.用参数区分函数重载的不同调用版本重72虚函数定义:在某基类中声明为virtual并在一个或多个派生类中被重新定义的成员函数
语法:virtual
函数返回类型函数名(参数表)
{函数体}用途:实现多态性,通过指向派生类对象的基类对象指针或对象引用,访问派生类中同名覆盖成员函数,72虚函数定义:73说明:虚函数是一个类的成员函数关键字virtual指明该成员函数为虚函数。当某一个类的一个类成员函数被定义为虚函数,则由该类派生出来的所有派生类中,该函数始终保持虚函数的特征。当在派生类中重新定义虚函数(overridingavirtualfunction,亦译作超载或覆盖)时,不必加关键字virtual。但重新定义时不仅要同名,而且它的参数表和返回类型全部与基类中的虚函数一样。73说明:74例#include<iostream.h>classPet//基类{public: virtualvoidSpeak(){cout<<"Howdoesapetspeak?"<<endl;}};classCat:publicPet //派生类{public: virtualvoidSpeak(){cout<<"miao!miao!"<<endl;}};classDog:publicPet //派生类{public: virtualvoidSpeak(){cout<<“wang!wang!"<<endl;}};voidmain(){ Petobj,*p1;//基类对象指针p1,基类对象obj Dogdog1; Catcat1; obj=dog1;//用Dog类对象给Pet类对象赋值
obj.Speak(); p1=&cat1; p1->Speak();}这个程序将输出结果如下:Howdoesapetspeak?miao!miao!对于函数obj.Speak()调用语句是静态绑定的(静态联编)。对于p1->Speak()调用语句是动态联编。74例#include<iostream.h>这个程序将75动态联编(dynamicbinding)亦称滞后联编(latebinding),对应于静态联编(staticbinding)。如果使用对象名和点成员选择运算符“.”引用特定的一个对象来调用虚函数,则被调用的虚函数是在编译时确定的(称为静态联编)如果使用基类指针或引用指明派生类对象,使用该指针调用虚函数(成员选择符用箭头号“->”),则程序动态地(运行时)选择该派生类的虚函数,称为动态联编。75动态联编(dynamicbinding)亦称滞后联编(76纯虚函数是在基类中只有说明而没有实现定义的虚函数,它的任何派生类都必须定义自己的实现版本。普通的虚函数在派生类中可以不重新定义。此时指向派生类对象的指针调用该函数时调用的是基类中定义的版本。纯虚函数定义形式:virtual类型函数名(参数表)=0;例如:在前面例子中对于从Circle、Triangle、Rectangle抽象出的公共基类Figure,求面积的运算是无实际意义的:virtualvoidarea(){ cout<<"Can'tdefineareaforanabstractionfigure"<<endl;}area()可以定义为纯虚函数。纯虚函数76纯虚函数是在基类中只有说明而没有实现定义的虚函数,它的任77抽象类说明凡是包含纯虚函数的类都是抽象类。或至少带有一个纯虚函数的类称为抽象类。因为纯虚函数是不能被调用的,包含纯虚函数的类是无法建立对象的。抽象类的作用是作为一个类族的共同基类,或者说,为一个类族提供一个公共接口。77抽象类说明78异常处理的基本思想计算机程序在机器上运行时会产生错误,这些错误对于编程人员可以预料到但却无法避免。在一个小型程序中,一旦程序运行时发生了异常,一般是将程序立即中断运行,从而无条件释放所有资源。而在一个较为复杂的软件中,函数与函数之间存在着各自明确的功能和相互间复杂的调用关系,发现错误的函数又并不具备处理错误的能力。78异常处理的基本思想计算机程序在机器上运行时会产生错误,这79C++的异常处理机制使得异常的引发和处理不需要在同一函数内完成,它可以将异常向上传播,这样底层的函数可以专门用以解决具体问题,而上层的调用者就可以在适当的位置针对不同类型的异常设计处理。
异常处理的基本思想79C++的异常处理机制使得异常的引发和处理不需要在同一函数80异常处理的机制C++语言提供了对处理异常情况的内部支持。在C++语言中,try、throw和catch语句就是用于实现异常处理的机制。有了C++程序的异常处理机制,程序可以向更高的执行上下文传递意想不到的事件,使C++程序能更好地从各种异常事件中进行有效地恢复,从而更好地执行80异常处理的机制C++语言提供了对处理异常情况的内部支持。81try{//错误侦测区块复合语句
throw异常类型表达式;//如果发生错误用throw语句抛出异常}catch(异常类型1){//错误处理区块复合语句}catch(异常类型2){//错误处理区块复合语句}……catch(…)//如果在前面并没有列举异常类型,则由此处理区块处理{//错误处理区块复合语句}//try-throw-catch后继续执行异常处理的机制81try异常处理的机制82#include<iostream>usingnamespacestd;inttry_modulus(int,int);voidmain(){try//代码保护段
{ cout<<"Modulus(5,2)is"<<try_modulus(5,2)<<endl; cout<<"Modulus(3,0)is"<<try_modulus(3,0)<<endl; cout<<"Modulus(8,5)is"<<try_modulus(8,5)<<endl; } catch(char*s)//处理异常
{cerr<<s;} cout<<"endoftheprogram.\n";}inttry_modulus(intx,inty){ if(y==0)//检查被除数是否为零,是则抛出异常
throw("exceptionofdividingzero!\n"); returnx%y;}Modulus(5,2)is1exceptionofdividingzero!endoftheprogram82#include<iostream>Modulus(5Q&A本讲结束!Q&A本讲结束!移动应用软件开发技术
第二讲:C++编程基础《移动应用软件开发技术》课程建设小组北京大学二零一一年*致谢:感谢Intel对本课程项目的支持
移动应用软件开发技术
第二讲:C++编程基础C++编程基础C++编程基础86C++标识符(Identifiers)程序设计语言中为变量、常量、类型、函数等取的名字称为标识符。标识符由大小写字母、数字和下划线组成,并且只能以字母或下划线开始。
例如:
9abc、*abc是不合法的标识符注意:标识符区分大小写标识符长度任意提倡使用“见名知义”的标识符避免使用系统已定义的标识符(系统保留字)3C++标识符(Identifiers)87关键字关键字在计算机中有预定的含义。关键字又称保留字,它们不能再被用户重新定义使用。
autoboolbreakcasecatchcharclassconstconst_castcontinuedefaultdeletedodoubleelseenumexplicitexternfalsefloatforfriendgotoifinlineintlongmutablenamespacenewoperatorprivateprotectedpublicregisterreturnshortsignedsizeofstaticstructswitchtemplatethisthrowtruetrytypedeftypeidtypenameunionunsignedusingvirtualvoidvolatilewhile4关键字88注释符C++语言保留了C语言中以/*开始,*/结束的注释,这种方式适用于多行的注释同时C++语言中还提供行注释符//,该注释在它的行结束处结束,适用于短注释。5注释符89数据类型数据类型是不同形式的信息在内存中分配方式的基本约定(不同类型的数据在内存中占用的字节数有所不同),是构造程序的基础。常量、变量甚至函数都具有自己的数据类型。类型名说明符整型int字符型char浮点型float布尔型bool空值型void五种基本数据类型6数据类型数据类型是不同形式的信息在内存中分配方式的基本约定90类型名字宽(字节)范围short[int]2–32768~32767signedshort[int]2–32768~32767unsignedshort[int]20~65535int4–2147483648~2147483647signed[int]4–2147483648~2147483647unsigned[int]40~4294967295long[int]4–2147483648~2147483647signedlong[int]4–2147483648~2147483647unsignedlong[int]40~4294967295char1–128~127signedchar1–128~127unsignedchar10~255float4double8longdouble8void032位机上各基本类型的字宽及表示范围7类型名字宽(字节)范围short[int]2–3276891变量变量是在程序执行过程中,其值可以改变的量;变量有3个基本要素:名字类型值8变量变量是在程序执行过程中,其值可以改变的量;92变量的名字是一种标识符,需用遵守标识符的规则区分大小写mycarMyCarMYCAR是三个变量名称不能使用关键字作为变量名“见名知意”常见命名方法:my_bookmyBookiMyBook9变量的名字是一种标识符,需用遵守标识符的规则93变量的类型C++中的变量在使用前必须定义,定义变量时必须指明变量的类型及名字。变量的类型包含数据类型和存储类型定义或说明变量的格式:<类型说明符><变量名表>;例如:staticintmy_car;10变量的类型C++中的变量在使用前必须定义,定义变量时必须94变量的值变量自身包含两个值:变量值:变量所表示的数据值地址值:变量在内存中的地址值变量可以在定义时初始化,给变量赋一个初值。
例如:inta=3,b=-78;doublearea=67.34;变量赋值,或更改变量值 例如:a=5;取变量地址值:通过“&”运算符来获得 例如:&a;11变量的值变量自身包含两个值:95C++提供另一种形式的初始化方法。例如,前面两个语句可改写为:
inta(3),b(-78);doublearea(67.34);12C++提供另一种形式的初始化方法。例如,前面两个语句可改96常量的定义格式定义格式:
const<类型说明符><常量名>=<常量值>
例如:
constdoublepi=3.141592653;13常量的定义格式定义格式:97整型常量十进制整型常量由0~9的数字组成,不能以0开头,没前缀例如:20189等八进制整型常量由0~7的数字组成,以0位前缀例如:032024等十六进制整型常量由0~9及a~f字母组成,0x或0X为前缀例如:0x1a0X3F等长整型常量后缀L(l),无符号整型常量后缀U(u)例如:123L12322U223212ul14整型常量十进制整型常量98字符串常量以一对双撇号括起来的字符序列例如:“Helloworld!\n”字符串常量中可以包含空格符、转义字符及其他字符,也可以包含汉字。由于双撇号是字符串的定界符,因此字符串中使用\”表示双撇号。字符串中字符的个数可以为任意数目字符串常量后面有一个结束符’\0’“a”与’a’不同15字符串常量以一对双撇号括起来的字符序列99运算符
运算符是指用来表示在数据上执行某些特定操作的符号。参与运算的数据称为操作数。(可以分别称为单目、双目和三目运算符)。算术运算符关系运算符逻辑运算符位操作运算符赋值运算符其他运算符16运算符运算符是指用来表示在数据100
逻辑运算真值表(真为非0,假为0)aba&&ba||b!a!b0000110非00110非000101非0非0110017逻辑运算真值表(真为非0,假为0)aba&&ba|101位操作运算符位运算符是对其操作数按其二进制形式逐位进行运算,参加位运算的操作数必须为整数。C++中所有的位运算符如下:~(按位求反) <<(左移)>>(右移) &(按位与) ^(按位异或) |(按位或)18位操作运算符位运算符是对其操作数按其二进制形式逐位进行运102选择语句利用选择语句可以实现具有选择结构的程序选择语句有两种条件语句(if语句)开关语句(switch语句)特点:具有一定的判断功能可以根据给定的条件来决定执行哪路分支中的语句19选择语句利用选择语句可以实现具有选择结构的程序103C++中有三种循环语句可用来实现循环结构:while语句、do_while语句和for语句。这些语句各有各的特点,而且常常可以互相替代。在编程时应根据需要选择最适合的循环语句。循环语句20循环语句104转向语句goto无条件转向语句,很少使用break退出语句continue结束本次循环语句转向语句用于改变语句的执行顺序21转向语句goto无条件转向语句,很少使用105枚举的定义枚举类型和枚举变量的定义格式如下,其中enum是枚举类型定义的关键字。enum枚举类型名{
枚举常量名1, 枚举常量名2,
…}枚举变量;//在定义枚举类型的同时定义枚举变量。例如:enumWeekDay{ Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday}today;也可在枚举类型定义后再定义枚举变量,格式如下:枚举类型名枚举变量。如:WeekDaytomorrow;22枚举的定义106枚举类型voidmain(){ enumWeakDay{ Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday}; WeakDayToday; Today=Friday; cout<<"Today="<<Today<<endl; Today=Sunday; cout<<"Today="<<Today<<endl;}Today=5Today=023枚举类型voidmain()Today=5107756-2354……107a[0]a[1]a[2]a[n-1]图一维数组数组是一些意义上相关的同类型变量的有序集合。每个数组元素都是一个变量,用来存放不同的值。数组元素引用形式:数组名[下标]数组24756-2354……107a[0]a[指针的概念1.指针:即变量的内存地址。2.指针变量指针变量是一种特殊的变量:
它存放的不是数据的值,而是另一个变量的地址。指针变量常常直接简称为指针。
指针指针的概念
指针109一个指针在定义以后,并不具体地指向某个变量,而只是确定了类型。可以对指针进行初始化,让它指向某个具体的变量。
“&”是取地址运算符,用在一个存储器操作数的前面,表示取存储器操作数的地址值。例如:
floatsalary;float*salary_ptr=&salary;就将指针salary_ptr初始化为变量salary的地址值,也即指向了具体的salary。
26一个指针在定义以后,并不具体地指向某个变量,而只是确定了110指针的赋值和引用
除了在指针定义时对它进行初始化外,还可以使用赋值运算来给指针赋以变量的地址值。例如:
inta=-8978;int*p;p=&a;这里,p被赋值为变量a的地址。也可以将一个已被赋值的指针赋给另一个相同类型的指针。例如:
doublea;double*x=&a,*y;y=x;这样一来,y就与x指向同一个变量a。27指针的赋值和引用111一个关于指针的例子。
#include<iostream.h>voidmain(){
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年买地过桥合同(1篇)
- 新乡医学院护理教育学
- 昏迷促醒护理核心要点解析
- 年产100万付金属镜架项目可行性研究报告模板立项申批备案
- 留学回国人员办理国外学历学位认证的官网操作流程留服中心复核所需时长
- 消化道出血的护理与急救措施
- 泌尿外科护理质量管理
- 皮肤疾病护理中的沟通技巧
- 管道安全检测与风险评估
- 2026 塑型进阶螺旋藻课件
- 新版电力重大事故隐患判定标准及治理监督管理规定解读
- 2026年北京市门头沟区街道办人员招聘笔试备考试题及答案解析
- 2026年学校防范非法宗教势力渗透工作机制
- 2026年成都市金牛区街道办人员招聘考试参考试题及答案解析
- 2026年四川省成都市网格员招聘笔试模拟试题及答案解析
- 建设项目提级论证方案
- 教科版六年级科学下册期中综合素养测试卷
- 2026年邢台市高层次人才引进495人笔试参考试题及答案解析
- 小学 四年级 语文 听力题 及听力材料
- 浙江省消防技术规范难点问题操作技术指南(2025 版)
- 高速公路平安百年品质工程标准化建设指南(专业篇 上篇)
评论
0/150
提交评论