C++AND UML习题及答案(给学生)

更新时间:2023-03-11 12:16:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

复习要求: 1.C++语言概述

(1)了解C++语言的基本符号。

(2)了解C++语言的词汇(保留字、标识符、常量、运算符、标点符号等)。 (3)掌握C++程序的基本框架(结构程序设计框架、面向对象程序设计框架等)。 (4)能够使用Visual C++ 6.0集成开发环境编辑、编译、运行与调试程序。 2.数据类型、表达式和基本运算

(1)掌握C++数据类型(基本类型、指针类型)及其定义方法。

(2)了解C++的常量定义(整型常量、字符常量、逻辑常量、实型常量、地址常量、符号常量)。 (3)掌握变量的定义与使用方法(变量的定义及初始化、全局变量、局部变量)。 (4)掌握C++运算符的种类、运算优先级和结合性。

(5)熟练掌握C++表达式类型及求值规则(赋值运算、算术运算符和算术表达式、关系运算符和关系表达式、逻辑运算符和逻辑表达式、条件运算、指针运算、逗号表达式)。 3.C++的基本语句

(1)掌握C++的基本语句,例如赋值语句、表达式语句、复合语句、输入、输出语句和空语句等。

(2)用if语句实现分支结构。

(3)用switch语句实现多分支选择结构。 (4)用for语句实现循环结构。 (5)用while语句实现循环结构。 (6)用do…while语句实现循环结构。

(7)转向语句(goto,continue,break和return)。 (8)掌握分支语句和循环语句的各种嵌套使用。 4.数组、指针与引用

(1)掌握一维数组的定义、初始化和访问,了解多维数组的定义、初始化和访问。 (2)了解字符串与字符数组。

(3)熟练掌握常用字符串函数(strlen,strcpy,strcat,strcmp,strstr等)。 (4)掌握指针与指针变量的概念、指针与地址运算符、指针与数组。 (5)掌握引用的基本概念、引用的定义与使用。

5.掌握函数的有关使用

(1)函数的定义方法和调用方法。 (2)函数的类型和返回值。

(3)形式参数与实在参数,参数值的传递。 (5)递归函数。 (6)函数重载。 (7)内联函数。

(8)带有默认参数值的函数。

6.熟练掌握类与对象的相关知识

(1)类的定义方式、数据成员、成员函数及访问权限(public,private,protected)。 (2)对象和对象指针的定义与使用。 (3)构造函数与析构函数。 (4)this指针的使用。

(5)对象数组与成员对象。 7.掌握类的继承与派生知识

(1)派生类的定义和访问权限。

(2)继承基类的数据成员与成员函数。 8. 了解UML的一些相关知识 (1)UML的发展史,建模对象。 (2)UML的四种类型事物。 (3)UML的四种关系。 9. 函数、运算符重载

(1)掌握常用运算符重载的方法,包括成员函数重载和友元函数的重载。 (2)掌握虚函数和纯虚函数的概念。

(3)在成员函数中实现自加,重载前置自加运算符,重载后置自加运算符. (4)重载加法运算函数operator+, 重载赋值运算函数operator=. (5)转换类型运算符 10.多态性

(1)运算符重载的运用。 (2)虚函数的定义。 (3)抽象类的声明。 一. 填空 1、

#include Using namespace std; int add(int a,int b); int main() {

int x,y,sum;

cout<<\:\

//在下画线处填上语句,完成用cin读入x和y cin>>x; cin>>y; sum=add(x,y);

cout<<\return 0; }

int add(int a,int b)

{

//在下画线处填上语句,完成计算a与b的和并返回之 return a+b; } 2、

#include Using namespace std; int main() {

char name[20];

cout<<”Hello,your name:”;

//在下画线处填上语句,完成将字符串输入到数组name中 cin>>name; //在下画线处填上语句,完成将name数组用cout输出 cout<

#include Using namespace std;

int mul(int x,int y) //mul函数1 { return x*y; }

int mul(int x,int y,int z) //mul函数2 { return x*y*z; } void main() {

int a=3,b=4,c=5;

//在下画线处填上语句,用于调用mul函数1 cout<

#include Using namespace std; main() {

int *p; //声明一个整型指针变量p

//在下画线处,用new关键字动态分配一个int型存储区,并将首地址赋给p

p=new int; *p = 10;

cout<<*p; //在下画线处填上语句,用于撤销指针p,释放p指向的存储空间 delete p; return 0; } 5

#include main() { int *p;

//在画线处填上语句,用new关键字动态分配一个int型存储区,并将首地址赋给p p=new int; if (!p) {

cout<<\return 1; }

//在下画线处填上语句,将p所指向的存储区赋值20 *p=20; cout<<*p;

//在下画线处填上语句,用于撤销指针p,释放p指向的存储空间 delete p; return 0;

}

6下列程序的输出结果是 7 。 #include using namespace std; int main() {

int i = 5;

int *p =& i;*p = 7; cout << i << endl; return 0; }

7下面是用来计算n的阶乘的递归函数,请将该函数的定义补充完整。(注:阶乘的定义是n!=n*(n-1)*...*2*1)

unsigned fact(unsigned n) { if ( n<= 1) return 1;

return n*fact(n-1) ; }

8与成员访问表达式p->name等价的表达式是 (*P).name 。 9.UML的全称为Unified Modeling Language,统一建模语言。

10.UML中有 结构事物,动作事物,分组事物,注释事物 四种类型事物。 11.UML中的四种关系为 依赖,关联,泛化,实现 。

12.类Sample的构造函数将形参data赋值给数据成员data。请将类定义补充完整。 class Sample{ public:

Sample(int data=0); Private: Int data; };

Sample::Sample(int data){ 【this->data=data;】 }

(13)若表达式(x+(y-z)*(m/n))+3中的变量均为double型,则表达式值的类型为【double】。 (14)有如下循环语句:

For(int i=50; i>20; i-=2) cout<

(15)利用表达式a[i]可以访问int型数组a中下标为i的元素。在执行了语句int *p=a;后,利用指针p也可访问该元素,相应的表达式是【*(p+i)】。

(16)下面是一个递归函数,其功能是使数组中的元素反序排列。请将函数补充完整。 void reverse(int *a, int size){ if(size<2) return; int k=a[0]; a[0]=a[size-1]; a[size-1]=k;

reverse(a+1, size-1 ); }

(17)有如下类定义: class Sample{ public: Sample(); ~Sample(); Private:

Static int date; };

将静态数据成员data初始化为0的语句是【int Sample::data = 0;】

(18)“图形”类Shape中定义了纯虚函数CalArea(),“三角形”类Triangle继承了类Shape,请将Triangle类中的CalArea函数补充完整。 class Shape{ public:

virtual int CalArea()=0;

}

class Triangle: public Shape{ public:

Triangle{int s, int h}: side(s),height(h) {}

【int CalArea(int side,int height)】 { return side*height/2 ; } private: int side; int height; };

二.选择题

1 建立派生类对象时,3种构造函数分别是a(基类的构造函数)、b(成员对象的构造函数)、c(派生类的构造函数),这3种构造函数的调用顺序为()

A abc B acb C cab D cba 答案:A

2下面描述中,符合结构化程序设计风格的是(A)

A)使用顺序、选择和重复(循环)三种基本控制结构表示程序的控制逻辑 B)模块只有一个入口,可以有多个出口 C)注重提高程序的执行效率 D)不使用goto语句

3下面概念中,不属于面向对象方法的是(D)

A)对象 B)继承 C)类 D)过程调用 4关于面向对象的程序设计方法,下列说法正确的是(D)

A)“封装性”指的是将不同类型的相关数据组合在一起,作为一个整体进行处理 B)“多态性”指的是对象的状态会根据运行时要求自动变化

C)基类的私有成员在派生类的对象中不可访问,也不占内存空间 D)在面向对象的程序设计中,结构化程序设计方法仍有着重要作用 5判断字符型变量ch是否为大写英文字母,应使用表达式(D) A ) ch>='A' & ch<='Z' B ) ch<='A' ||ch>='Z'

C ) 'A'<=ch<='Z' D ) ch>='A' && ch<='Z'

6已知下列语句中的x和y都是int型变量,其中错误的语句(C) A ) x=y++; B ) x=++y; C ) (x+y)++; D ) ++x=y; 7执行语句序列(D) int n; cin >> n; switch(n) { case 1:

case 2: cout << '1'; case 3:

case 4: cout << '2'; break; default: cout << '3'; }

时,若键盘输入1,则屏幕显示 A)1 B)2 C)3 D)12

8关于动态存储分配,下列说法正确的是(B)

A)new和delete是C++语言中专门用于动态内存分配和释放的函数 B)动态分配的内存空间也可以被初始化

C)当系统内存不够时,会自动回收不再使用的内存单元,因此程序中不必用delete释放内存空间

D)当动态分配内存失败时,系统会立刻崩溃,因此一定要慎用new 9)对类的构造函数和析构函数描述正确的是(A) A 构造函数可以重载,析构函数不能重载

B 构造函数不可以重载,析构函数可以重载 C 构造函数可以重载,析构函数也可以重载 D构造函数不能重载,析构函数也不能重载 (10)下列程序的输出结果是(A) #include using namespace std; int main() {

char a[] = \ char *ptr = a; while (*ptr) {

if (*ptr >= 'a' && *ptr <= 'z')

cout << char(*ptr + 'A' -'a'); else cout << *ptr; ptr++; }

return 0; }

A ) HELLO, WORLD B ) Hello, World C ) hELLO, wORLD D ) hello, world

11) 已知:int m=10;在下列定义引用的语句中,正确的是(A) A ) int &x=m; B )int y=&m;

C )int &z; D ) int &t=&m; (17)下列函数原型声明中错误的是(D) A ) void Fun(int x=0, int y=0); B ) void Fun(int x, int y); C ) void Fun(int x, int y=0); D ) void Fun(int x=0, int y);

(12)已知程序中已经定义了函数test,其原型是int test(int, int, int);,则下列重载形式中正确的是(B)

A ) char test(int,int,int);

B ) double test(int,int,double); C ) int test(int,int,int=0);

D ) float test(int,int,float=3.5F);

(13)已知函数f的原型是:void f(int *a, long &b); 变量v1、v2的定义是:int v1;long v2;,正

确的调用语句是(C) A) f(v1, &v2); B) f(v1, v2); C) f(&v1, v2); D) f(&v1, &v2); (14)有以下类定义 class MyClass {

public:

MyClass(){cout<<1;} };

则执行语句MyClass a, b[2], *p[2];后,程序的输出结果是(B) A)11 B)111 C)1111 D)11111

(15)关于动态存储分配,下列说法正确的是(B)

A)new和delete是C++语言中专门用于动态内存分配和释放的函数 B)动态分配的内存空间也可以被初始化

C)当系统内存不够时,会自动回收不再使用的内存单元,因此程序中不必用delete释放内存空间

D)当动态分配内存失败时,系统会立刻崩溃,因此一定要慎用new (16)关于友元,下列说法错误的是(A)

A)如果类A是类B的友元,那么类B也是类A的友元

B)如果函数fun()被说明为类A的友元,那么在fun()中可以访问类A的私有成员 C)友元关系不能被继承

D)如果类A是类B的友元,那么类A的所有成员函数都是类B的友元 (17)在公有派生的情况下,派生类中定义的成员函数只能访问原基类的(C) A)公有成员和私有成员 B)私有成员和保护成员

C)公有成员和保护成员 D)私有成员、保护成员和公有成员 (18)在C++中用来实现运行时多态性的是(D)

A)重载函数 B)析构函数 C)构造函数 D)虚函数

(19)一个类可以同时继承多个类,称为多继承。下列关于多继承和虚基类的表述中,错误的是(C)

A)每个派生类的构造函数都要为虚基类构造函数提供实参 B)多继承时有可能出现对基类成员访问的二义性问题 C)使用虚基类可以解决二义性问题并实现运行时的多态性 D)建立最派生类对象时,虚基类的构造函数会首先被调用 (20)在一个类体的下列声明中,正确的纯虚函数声明是(A) A) virtual void vf()=0; B) void vf(int)=0;

C) virtual int vf(int); D) virtual void vf(int) { } (21)在下面的运算符重载函数的原型中,错误的是(A) A) Volume operator - (double, double); B) double Volume::operator- (double); C) Volume Volume: :operator - (Volume); D) Volume operator - (Volume, Volume);

(22)下列关于继承方式的描述中,错误的是(D)

A)如果不显式地指定继承方式,缺省的继承方式是私有(private)

B)采用公有继承方式时,基类中的公有成员在派生类中仍然是公有成员 C)采用保护继承方式时,基类中的保护成员在派生类中仍然是保护成员

D)采用私有继承方式时,基类中的私有成员在派生类中仍然是私有成员 (23)已知函数FA调用FB,若要把这两个函数定义在同一个文件中,则: D A)FA必须定义在FB之前 B)FB必须定义在FA之前

C)若FA定义在FB之后,则FA的原型必须出现在FB的定义之前 D)若FB定义在FA之后,则FB的原型必须出现在FA的定义之前 (24)有如下两个类定义 class AA{}; class BB{ AA v1,*v2; BB v3; int *v4; };

其中有一个成员变量的定义是错误的,这个变量是:C

A)v1 B)v2 C)v3 D)v4 (25)有如下类定义 (13)B: class XX{ int xdata; public:

XX(int n=0) : xdata (n) { } };

class YY : public XX{ int ydata; public:

YY(int m=0, int n=0) : XX(m), ydata(n) { } };

YY类的对象包含的数据成员的个数是 A)1 B)2 C)3 D)4

(26)下列有关运算符函数的描述中,错误的是:C A)运算符函数的名称总是以operator为前缀 B)运算符函数的参数可以是对象

C)运算符函数只能定义为类的成员函数

D)在表达式中使用重载的运算符相当于调用运算符重载函数 (27)下列字符串可以用作C++标识符的是:D

A)2009var B)goto C)test - 2009 D)_123 (28)下列枚举类型的定义中,包含枚举值3的是:A A)enum test {RED, YELLOW, BLUE, BLACK}; B)enum test {RED, YELLOW=4, BLUE, BLACK}; C)enum test {RED=-1, YELLOW,BLUE, BLACK}; D)enum test {RED, YELLOW=6, BLUE, BLACK}; (29)有如下程序段:C

int i=1; while (1) { i++;

if(i == 10) break;

if(i%2 == 0) cout << '*'; }

执行这个程序段输出字符*的个数是 A)10 B)3 C)4 D)5 (30)已知数组arr的定义如下:D int arr[5] = {1,2,3,4,5};

下列语句中输出结果不是2的是

A)cout << *arr+1 <

if (n == 0) return 1; else if (n == 1) return 2; else return fib(n-1)+fib(n-2); }

若执行函数调用表达式fib(2),函数fib被调用的次数是 A)1 B)2 C)3 D)4

(32)Sample是一个类,执行下面语句后,调用Sample类的构造函数的次数是: D Sample a[2], *p = new Sample;

A)0 B)1 C)2 D)3

(33)下列关于虚基类的描述中,错误的是: C A)使用虚基类可以消除由多继承产生的二义性

B)构造派生类对象时,虚基类的构造函数只被调用一次 C)声明“class B : virtual public A”说明类B为虚基类 D)建立派生类对象时,首先调用虚基类的构造函数 (34)下列关于运算符重载的描述中,错误的是: C A)::运算符不能重载

B)类型转换运算符只能作为成员函数重载

C)将运算符作为非成员函数重载时必须定义为友元 D)重载[]运算符应完成“下标访问”操作 (35)有如下类定义 class A { char *a; public: A():a(0){}

A(char *aa){ //把aa所指字符串拷贝到a所指向的存储空间 a= A ; strcpy(a,aa); strcpy(a,aa); }

~A() {delete []a;}

};

横线处应填写的表达式是

A)new char[strlen(aa)+1] B)char[strlen(aa)+1] C)char[strlen(aa)] D)new char[sizeof(aa)-1]

(36)将运算符重载为类成员函数时,其参数表中没有参数,说明该运算是: (B)

A)不合法的运算符 B)一元运算符 C)无操作数的运算符 D)二元运算符(37)下列选项中不属于结构化程序设计原则的是:A A)可封装 B)自顶向下 C)模块化 D)逐步求精

第 一 章 概述

1-1 简述计算机程序设计语言的发展历程。 解:

迄今为止计算机程序设计语言的发展经历了机器语言、汇编语言、高级语言等阶段,C++语言是一种面向对象的编程语言,也属于高级语言。 1-2 面向对象的编程语言有哪些特点? 解:

面向对象的编程语言与以往各种编程语言有根本的不同,它设计的出发点就是为了能更直接的描述客观世界中存在的事物以及它们之间的关系。面向对象的编程语言将客观事物看作具有属性和行为的对象,通过抽象找出同一类对象的共同属性(静态特征)和行为(动态特征),形成类。通过类的继承与多态可以很方便地实现代码重用,大大缩短了软件开发周期,并使得软件风格统一。因此,面向对象的编程语言使程序能够比较直接地反问题域的本来面目,软件开发人员能够利用人类认识事物所采用的一般思维方法来进行软件开发。C++语言是目前应用最广的面向对象的编程语言。

1-3 什么是结构化程序设计方法?这种方法有哪些优点和缺点? 解:

结构化程序设计的思路是:自顶向下、逐步求精;其程序结构是按功能划分为若干个基本模块;各模块之间的关系尽可能简单,在功能上相对独立;每一模块内部均是由顺序、选择和循环三种基本结构组成;其模块化实现的具体方法是使用子程序。结构化程序设计由于采用了模块分解与功能抽象,自顶向下、分而治之的方法,从而有效地将一个较复杂的程序系统设计任务分解成许多易于控制和处理的子任务,便于开发和维护。 虽然结构化程序设计方法具有很多的优点,但它仍是一种面向过程的程序设计方法,它把数据和处理数据的过程分离为相互独立的实体。当数据结构改变时,所有相关的处理过程都要进行相应的修改,每一种相对于老问题的新方法都要带来额外的开销,程序的可重用性差。 由于图形用户界面的应用,程序运行由顺序运行演变为事件驱动,使得软件使用起来越来越方便,但开发起来却越来越困难,对这种软件的功能很难用过程来描述和实现,使用面向过程的方法来开发和维护都将非常困难。

1-4 什么是对象?什么是面向对象方法?这种方法有哪些特点? 解:

从一般意义上讲,对象是现实世界中一个实际存在的事物,它可以是有形的,也可以是无形的。对象是构成世界的一个独立单位,它具有自己的静态特征和动态特征。面向对象方法中的对象,是系统中用来描述客观事物的一个实体,它是用来构成系统的一个基本单位,由一组属性和一组行为构成。

面向对象的方法将数据及对数据的操作方法放在一起,作为一个相互依存、不可分离的整体--对象。对同类型对象抽象出其共性,形成类。类中的大多数数据,只能用本类的方法进行

处理。类通过一个简单的外部接口,与外界发生关系,对象与对象之间通过消息进行通讯。这样,程序模块间的关系更为简单,程序模块的独立性、数据的安全性就有了良好的保障。通过实现继承与多态性,还可以大大提高程序的可重用性,使得软件的开发和维护都更为方便。

面向对象方法所强调的基本原则,就是直接面对客观存在的事物来进行软件开发,将人们在日常生活中习惯的思维方式和表达方式应用在软件开发中,使软件开发从过分专业化的方法、规则和技巧中回到客观世界,回到人们通常的思维。 1-5 什么叫做封装? 解:

封装是面向对象方法的一个重要原则,就是把对象的属性和服务结合成一个独立的系统单位,并尽可能隐蔽对象的内部细节。 第 二 章 C++简单程序设计 2-1 C++语言有那些主要特点和优点? 解:

C++语言的主要特点表现在两个方面,一是全面兼容C,二是支持面向对象的方法。C++是一个更好的C,它保持了C的简洁、高效、接近汇编语言、具有良好的可读性和可移植性等特点,对C的类型系统进行了改革和扩充,因此C++比C更安全,C++的编译系统能检查出更多的类型错误。 C++语言最重要的特点是支持面向对象。 2-2 下列标识符哪些是合法的?

Program, -page, _lock, test2, 3in1, @mail, A_B_C_D 解:

Program, _lock, test2, A_B_C_D是合法的标识符,其它的不是。 2-3 解释每条语句的作用是什么? #include void main(void) {

cout<<\

cout<<\}

解:

#include //指示编译器将文件iostream.h中的代码 //嵌入到该程序中该指令所在的地方

void main() //主函数名,void 表示函数没有返回值 { //函数体标志

cout<<\输出字符串Hello!到标准输出设备(显示器)上。 cout<<\输出字符串Welcome to c++! }

在屏幕输出如下: Hello!

Welcome to c++!

2-4 使用关键字const而不是#define语句的好处有哪些? 解:

const定义的常量是有类型的,所以在使用它们时编译器可以查错;而且,这些变量在调试时仍然是可见的。

2-5 请写出C++语句声明一个常量PI,值为3.1416;再声明一个浮点型变量a,把PI的值赋给a。 解:

const float PI = 3.1416; float a = PI;

2-6 在下面的枚举类型中,Blue的值是多少?

enum COLOR { WHITE, BLACK = 100, RED, BLUE, GREEN = 300 }; 解: Blue = 102

2-7 注释有什么作用?C++中有哪几种注释的方法?他们之间有什么区别? 解:

注释在程序中的作用是对程序进行注解和说明,以便于阅读。编译系统在对源程序进行编译时不理会注释部分,因此注释对于程序的功能实现不起任何作用。而且由于编译时忽略注释部分,所以注释内容不会增加最终产生的可执行程序的大小。适当地使用注释,能够提高程序的可读性。在C++中,有两种给出注释的方法:一种是延用C语言方法,使用\和\括起注释文字。另一种方法是使用\,从\开始,直到它所在行的行尾,所有字符都被作为注释处理。

2-8 什么叫做表达式?x = 5 + 7是一个表达式吗?它的值是多少? 解:

任何一个用于计算值的公式都可称为表达式。x = 5 + 7是一个表达式,它的值为12。 2-9 下列表达式的值是多少? 1. 201 / 4 2. 201 % 4 3. 201 / 4.0 解: 1. 50 2. 1 3. 50.25

2-10 执行完下列语句后,a、b、c三个变量的值为多少? a = 30; b = a++; c = ++a; 解:

a:32 ; b:30 ; c:32;

2-11 在一个for循环中,可以初始化多个变量吗?如何实现? 解:

在for循环设置条件的第一个\前,用,分隔不同的赋值表达式。 例如:

for (x = 0, y = 10; x < 100; x++, y++) 2-12 执行完下列语句后,n的值为多少? int n;

for (n = 0; n < 100; n++)

解:

n的值为100

2-13 写一条for语句,计数条件为n从100到200,步长为2;然后用while和do…while语句完成同样的循环。 解: for循环:

for (int n = 100; n <= 200; n += 2); while循环: int x = 100;

while (n <= 200) n += 2;

do…while循环: int n = 100; do {

n += 2;

} while(n <= 200);

2-14 if ( x = 3 ) 和 if (x = = 3) 这两条语句的差别是什么? 解:

语句if(x = 3)把3赋给x,赋值表达式的值为true,作为if语句的条件;语句if(x == 3)首先判断x的值是否为3,若相等条件表达式的值为ture,否则为false。

2-15什么叫做局部变量?什么叫做全局变量,如何使用全局变量? 解:

局部变量,一般来讲就是具有块作用域的变量;全局变量,就是具有文件作用域的变量。

2-16 已知x、y两个变量,写一条简单的if语句,把较小的的值赋给原本值较大的变量。 解: if (x > y) x = y;

else // y > x || y == x y = x;

2-17 修改下面这个程序中的错误,改正后它的运行结果是什么? #include void main() int i int j;

i = 10; /* 给i赋值 j = 20; /* 给j赋值 */

cout <<\输出结果 */ return 0; }

解: 改正:

#include int main() { int i; int j;

i = 10; // 给i赋值 j = 20; /* 给j赋值 */

cout <<\输出结果 */ return 0; }

程序运行输出: i + j = 30

2-18 编写一个程序,运行时提示输入一个数字,再把这个数字显示出来。 解: 源程序:

#include int main() { int i;

cout <<\请输入一个数字:\cin >> i;

cout <<\您输入一个数字是\return 0; }

程序运行输出: 请输入一个数字:5 您输入一个数字是5

2-19 运行下面的程序,观察其输出,与你的设想是否相同? #include int main() {

unsigned int x;

unsigned int y = 100; unsigned int z = 50; x= y - z;

cout <<\x = z - y;

cout <<\return 0; }

解:

2-20什么叫常量?什么叫变量?

解:

所谓常量是指在程序运行的整个过程中其值始终不可改变的量,除了用文字表示常量外,也可以为常量命名,这就是符号常量;在程序的执行过程中其值可以变化的量称为变量,变量是需要用名字来标识的。

2-21写出下列表达式的值: 1. 2 < 3 && 6 < 9 2. ! ( 4<7 )

3. ! ( 3 > 5) || (6 < 2 ) 解: 1. true 2. false 3. true

2-22编写一个完整的程序,运行时向用户提问\你考试考了多少分?(后判断其等级,显示出来。规则如下: 解:

#include

void main() {

int i,score;

cout <<\你考试考了多少分?(0~100):\cin >> score;

if (score>100 || score<0)

cout <<\分数值必须在0到100之间!\else {

i = score/10; switch (i) {

case 10: case 9:

cout <<\你的成绩为优!\break; case 8:

cout <<\你的成绩为良!\break;

0~100)\,接收输入case 7: case 6:

cout <<\你的成绩为中!\break; default:

cout <<\你的成绩为差!\} } }

程序运行输出:

你考试考了多少分?(0~100):85 你的成绩为良!

2-23用穷举法找出1~100间的质数,显示出来。分别使用while,do-while,for循环语句实现。 解: 源程序:

使用while循环语句: #include #include void main() {

int i,j,k,flag; i = 2;

while(i <= 100) {

flag = 1; k = sqrt(i); j = 2;

while (j <= k) {

if(i%j == 0) {

flag = 0; break; } j++; }

if (flag)

cout << i <<\是质数.\i++; } }

使用do…while循环语句: #include #include void main() {

int i,j,k,flag; i = 2; do{ flag = 1; k = sqrt(i); j = 2; do{

if(i%j == 0) {

flag = 0; break; } j++;

}while (j <= k); if (flag)

cout << i <<\是质数.\i++;

}while(i <= 100); }

使用for循环语句: #include #include void main() {

int i,j,k,flag;

for(i = 2; i <= 100; i++) {

flag = 1; k = sqrt(i);

for (j = 2; j <= k; j++) {

if(i%j == 0) {

flag = 0; break; } }

if (flag)

cout << i <<\是质数.\

} }

程序运行输出: 2是质数. 3是质数. 5是质数. 7是质数. 11是质数. 13是质数. 17是质数. 19是质数. 23是质数. 29是质数. 31是质数. 37是质数. 41是质数. 43是质数. 47是质数. 53是质数. 59是质数. 61是质数. 67是质数. 71是质数. 73是质数. 79是质数. 83是质数. 89是质数. 97是质数.

2-24 比较Break语句与Continue语句的不同用法。 解:

Break使程序从循环体和switch语句内跳出,继续执行逻辑上的下一条语句,不能用在别处; continue 语句结束本次循环,接着开始判断决定是否继续执行下一次循环;

2-25 在程序中定义一个整型变量,赋以1~100的值,要求用户猜这个数,比较两个数的大小,把结果提示给用户,直到猜对为止。分别使用while、do…while语句实现循环。 解:

//使用while语句 #include void main() { int n = 18; int m = 0;

while(m != n) {

cout <<\请猜这个数的值为多少?(0~~100):\cin >> m; if (n > m)

cout <<\你猜的值太小了!\else if (n < m)

cout <<\你猜的值太大了!\else

cout <<\你猜对了!\} }

//使用do…while语句 #include

void main() { int n = 18; int m = 0; do{

cout <<\请猜这个数的值为多少?(0~~100):\cin >> m; if (n > m)

cout <<\你猜的值太小了!\else if (n < m)

cout <<\你猜的值太大了!\else

cout <<\你猜对了!\}while(n != m); }

程序运行输出:

请猜这个数的值为多少?(0~~100):50 你猜的值太大了!

请猜这个数的值为多少?(0~~100):25 你猜的值太大了!

请猜这个数的值为多少?(0~~100):10 你猜的值太小了!

请猜这个数的值为多少?(0~~100):15 你猜的值太小了!

请猜这个数的值为多少?(0~~100):18 你猜对了!

第三章 函数

3-1 C++中的函数是什么?什么叫主调函数,什么叫被调函数,二者之间有什么关系?如何调用一个函数?

解:

一个较为复杂的系统往往需要划分为若干子系统,高级语言中的子程序就是用来实现这种模块划分的。C和C++语言中的子程序就体现为函数。调用其它函数的函数被称为主调函数,被其它函数调用的函数称为被调函数。一个函数很可能既调用别的函数又被另外的函数调用,这样它可能在某一个调用与被调用关系中充当主调函数,而在另一个调用与被调用关系中充当被调函数。

调用函数之前先要声明函数原型。按如下形式声明: 类型标识符 被调函数名 (含类型说明的形参表);

声明了函数原型之后,便可以按如下形式调用子函数: 函数名(实参列表)

3-2 什么叫内联函数?它有哪些特点?

解:

定义时使用关键字 inline的函数叫做内联函数;

编译器在编译时在调用处用函数体进行替换,节省了参数传递、控制转移等开销; 内联函数体内不能有循环语句和switch语句;

内联函数的定义必须出现在内联函数第一次被调用之前; 对内联函数不能进行异常接口声明;

3-3 函数原型中的参数名与函数定义中的参数名以及函数调用中的参数名必须一致吗?

解:

不必一致,所有的参数是根据位置和类型而不是名字来区分的。

3-4 编写函数把华氏温度转换为摄氏温度,公式为:C = (F - 32) * 5/9; 在主程序中提示用户输入一个华氏温度,转化后输出相应的摄氏温度。

解:

源程序见\实验指导\部分实验三

3-5 编写函数判断一个数是否是质数,在主程序中实现输入、输出。

解:

#include #include

int prime(int i); //判一个数是否是质数的函数

void main() { int i;

cout <<\请输入一个整数:\cin >> i; if (prime(i))

cout << i <<\是质数.\else

cout << i <<\不是质数.\}

int prime(int i) {

int j,k,flag; flag = 1; k = sqrt(i);

for (j = 2; j <= k; j++) {

if(i%j == 0) {

flag = 0; break; } }

if (flag) return 1; else return 0; }

程序运行输出:

请输入一个整数:1151 1151是质数.

3-6 什么叫作嵌套调用?什么叫作递归调用? 解:

函数允许嵌套调用,如果函数1调用了函数2,函数2再调用函数3,便形成了函数的嵌套调用。

函数可以直接或间接地调用自身,称为递归调用。

3-7 用递归的方法编写函数求Fibonacci 级数,公式为fib(n) = fib(n-1) + fib(n-2),n>2; fib(1) = fib(2) = 1;观察递归调用的过程。

3-8 实现重载函数Double(x),返回值为输入参数的两倍;参数分别为整型、长整型、浮点型、双精度型,返回值类型与参数一样。 解: 源程序:

#include

int Double(int); long Double(long); float Double(float); double Double(double);

int main() {

int myInt = 6500;

long myLong = 65000; float myFloat = 6.5F;

double myDouble = 6.5e20;

int doubledInt; long doubledLong; float doubledFloat; double doubledDouble;

cout <<\cout <<\cout <<\cout <<\

doubledInt = Double(myInt); doubledLong = Double(myLong); doubledFloat = Double(myFloat); doubledDouble = Double(myDouble);

cout <<\cout <<\cout <<\cout <<\

return 0; }

int Double(int original) {

cout <<\

return 2 * original; }

long Double(long original) {

cout <<\return 2 * original; }

float Double(float original) {

cout <<\return 2 * original; }

double Double(double original) {

cout <<\return 2 * original; }

程序运行输出: myInt: 6500 myLong: 65000 myFloat: 6.5

myDouble: 6.5e+20 In Double(int) In Double(long) In Double(float) In Double(double) DoubledInt: 13000 DoubledLong: 130000 DoubledFloat: 13

DoubledDouble: 1.3e+21

3-9 定义一个Rectangle类,有长itsWidth、宽itsLength等属性,重载其构造函数Rectangle()和Rectangle(int width, int length)。 解: 源程序:

#include

class Rectangle {

public:

Rectangle();

Rectangle(int width, int length); ~Rectangle() {}

int GetWidth() const { return itsWidth; } int GetLength() const { return itsLength; } private: int itsWidth; int itsLength; };

Rectangle::Rectangle() {

itsWidth = 5; itsLength = 10; }

Rectangle::Rectangle (int width, int length) {

itsWidth = width; itsLength = length; }

int main() {

Rectangle Rect1;

cout <<\cout <<\

int aWidth, aLength; cout <<\cin >> aWidth;

cout <<\cin >> aLength;

Rectangle Rect2(aWidth, aLength);

cout <<\cout <<\return 0; }

程序运行输出: Rect1 width: 5 Rect1 length: 10 Enter a width: 20

Enter a length: 50

Rect2 width: 20 Rect2 length: 50

3-10 对Point类重载++(自增)、--(自减)运算符 解:

#include

class Point {

public:

Point& operator++(); Point operator++(int);

Point& operator--(); Point operator--(int);

Point() { _x = _y = 0; }

int x() { return _x; } int y() { return _y; } private: int _x, _y; };

Point& Point::operator++() { _x++; _y++;

return *this; }

Point Point::operator++(int) {

Point temp = *this; ++*this; return temp; }

Point& Point::operator--() { _x--; _y--;

return *this; }

Point Point::operator--(int) {

Point temp = *this; --*this;

return temp; }

void main() {

Point A;

cout <<\的值为:\A++;

cout <<\的值为:\++A;

cout <<\的值为:\A--;

cout <<\的值为:\--A;

cout <<\的值为:\}

程序运行输出: A的值为:0 , 0 A的值为:1 , 1 A的值为:2 , 2 A的值为:1 , 1 A的值为:0 , 0

第四 章 面向对象

4-1 解释public和private的作用,公有类型成员与私有类型成员有些什么区别? 解:

公有类型成员用public关键字声明,公有类型定义了类的外部接口;私有类型的成员用private关键字声明,只允许本类的函数成员来访问,而类外部的任何访问都是非法的,这样,私有的成员就整个隐蔽在类中,在类的外部根本就无法看到,实现了访问权限的有效控制。

4-2 protected关键字有何作用? 解:

protected用来声明保护类型的成员,保护类型的性质和私有类型的性质相似,其差别在于继承和派生时派生类的成员函数可以访问基类的保护成员。

4-3 构造函数和析构函数有什么作用? 解:

构造函数的作用就是在对象被创建时利用特定的值构造对象,将对象初始化为一个特定的状态,使此对象具有区别于彼对象的特征,完成的就是是一个从一般到具体的过程,构造函数在对象创建的时候由系统自动调用。

析构函数与构造函数的作用几乎正好相反,它是用来完成对象被删除前的一些清理工作,也就是专门作扫尾工作的。一般情况下,析构函数是在对象的生存期即将结束的时刻由系统自动调用的,它的调用完成之后,对象也就消失了,相应的内存空间也被释放。

4-4 数据成员可以为公有的吗?成员函数可以为私有的吗? 解:

可以,二者都是合法的。数据成员和成员函数都可以为公有或私有的。但数据成员最好定义为私有的。

4-5 已知class A中有数据成员int a,如果定义了A的两个对象A1、A2,它们各自的数据成员a的值可以不同吗? 解:

可以,类的每一个对象都有自己的数据成员。

第五 章 数组、指针与字符串 5-1 数组A[10][5][15]一共有多少个元素? 解: 10×5×15 = 750 个元素

5-2 在数组A[20]中第一个元素和最后一个元素是哪一个? 解:

第一个元素是A[0],最后一个元素是A[19]。

5-3 用一条语句定义一个有五个元素的整型数组,并依次赋予1~5的初值。 解: 源程序:

int IntegerArray[5] = { 1, 2, 3, 4, 5 }; 或:int IntegerArray[] = { 1, 2, 3, 4, 5 };

5-4 已知有一个数组名叫oneArray,用一条语句求出其元素的个数。 解: 源程序:

nArrayLength = sizeof(oneArray) / sizeof(oneArray[0]);

5-5 用一条语句定义一个有5×3个元素的二维整型数组,并依次赋予1~15的初值。

解: 源程序:

int theArray[5][3] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };

或:int theArray[5][3] = { {1,2,3}, {4,5,6}, {7,8,9}, {10,11,12},{13,14,15} };

5-6 运算符*和&的作用是什么? 解:

*称为指针运算符,是一个一元操作符,表示指针所指向的对象的值;&称为取地址运算符,也是一个一元操作符,是用来得到一个对象的地址。

5-7 什么叫做指针?指针中储存的地址和这个地址中的值有何区别? 解:

指针是一种数据类型,具有指针类型的变量称为指针变量。指针变量存放的是另外一个对象的地址,这个地址中的值就是另一个对象的内容。

5-8 定义一个整型指针,用new语句为其分配包含10个整型元素的地址空间。 解: 源程序:

int *pInteger = new int[10];

5-9 声明下列指针:float类型变量的指针pFloat,char类型的指针pString和int类型的指针pint。 解:

float *pfloat; char *pString; intr *pint;

5-10 给定float类型的指针fp,写出显示fp所指向的值的输出流语句。 解:

cout <<\

5-11 程序中定义一个double类型变量的指针。分别显示指针占了多少字节和指针所指的变量占了多少字节。 解:

double *counter;

cout <<\

cout << '\\nSize of addressed value == \

5-12 const int * p1 和 int * const p2的区别是什么? 解:

const int * p1 声明了一个指向整型常量的指针p1,因此不能通过指针p1来改变它所指向的整型值;int * const p2声明了一个指针型常量,用于存放整型变量的地址,这个指针一旦初始化后,就不能被重新赋值了。

5-13 定义一个整型变量a,初值为5,一个整型指针p,通过p把a的值改为10 解:

void main() {

int a=5; int *p = &a; *p = 10; }

5-14 下列程序有何问题,请仔细体会使用指针时应避免出现这个的问题。 #include int main() {

int *p;

int *pInt = 9;

std::cout <<\return 0; }

解:

指针p没有初始化,也就是没有指向某个确定的内存单元,它指向内存中的一个随机地址,给这个随机地址赋值是非常危险的。

5-15 下列程序有何问题,请改正;仔细体会使用指针时应避免出现的这个问题。 #include int Fn1(); int main() {

int a = Fn1();

cout <<\return 0; }

int Fn1() {

int * p = new int (5); return *p; }

解:

此程序中给*p分配的内存没有被释放掉。 改正:

#include int* Fn1();

int main() {

int *a = Fn1();

cout <<\delete a; return 0; }

int* Fn1() {

int * p = new int (5); return p; }

5-16引用和指针有何区别?何时只能使用指针而不能使用引用?

解:

指针可以为NULL值,引用是一个别名,不能为NULL值;指针可以被赋值,引用只可以被初始化,不可以被赋为另一个对象的别名;指针可以指向堆中空间,引用不可以指向堆中空间。

当需要对变量重新赋以另外的地址或赋值为NULL时只能使用指针。

5-17 定义一个整型变量a,一个整型指针p,一个引用r,通过p把a的值改为10,通过r把a的值改为5

解:

void main() { int a;

int *p = &a; int &r = a; *p = 10; r = 5; }

5-18 比较值调用和引用调用的相同点与不同点。 解:

值调用是指当发生函数调用时,给形参分配内存空间,并用实参来初始化形参(直接将实参的值传递给形参)。这一过程是参数值的单向传递过程,一旦形参获得了值便与实参脱离关系,此后无论形参发生了怎样的改变,都不会影响到实参。 引用调用将引用作为形参,在执行主调函数中的调用语句时,系统自动用实参来初始化形参。这样形参就成为实参的一个别名,对形参的任何操作也就直接作用于实参。

第 六 章 继承与派生

6-1 比较类的三种继承方式public公有继承、protected保护继承、private私有继承之间的差别。 解:

不同的继承方式,导致不同访问属性的基类成员在派生类中的访问属性也有所不同: 公有继承,使得基类public(公有)和protected(保护)成员的访问属性在派生类中不变,而基类private(私有)成员不可访问。 私有继承,使得基类public(公有)和protected(保护)成员都以private(私有)成员身份出现在派生类中,而基类private(私有)成员不可访问。

保护继承中,基类public(公有)和protected(保护)成员都以protected(保护)成员身份出现在派生类中,而基类private(私有)成员不可访问。

6-2 定义一个哺乳动物Mammal类,再由此派生出狗Dog类,定义一个Dog类的对象,观察基类与派生类的构造函数与析构函数的调用顺序。 解: 源程序:

#include

enum myColor{ BLACK, WHITE }; class Mammal {

public:

// constructors Mammal(); ~Mammal();

//accessors

int GetAge() const { return itsAge; } void SetAge(int age) { itsAge = age; } int GetWeight() const { return itsWeight; }

void SetWeight(int weight) { itsWeight = weight; }

//Other methods

void Speak() const { cout <<\

protected: int itsAge; int itsWeight; };

class Dog : public Mammal {

public: Dog(); ~Dog();

myColor GetColor() const { return itsColor; }

void SetColor (myColor color) { itsColor = color; }

void WagTail() { cout <<\

private:

myColor itsColor; };

Mammal::Mammal(): itsAge(1), itsWeight(5) {

cout <<\}

Mammal::~Mammal() {

cout <<\}

Dog::Dog(): itsColor (WHITE) {

cout <<\}

Dog::~Dog() {

cout <<\}

int main() {

Dog Jack; Jack.Speak(); Jack.WagTail();

cout <<\

return 0; }

程序运行输出:

Mammal constructor... Dog constructor... Mammal sound!

Tail wagging... Fido is 1 years old Dog destructor... Mammal destructor...

6-3 定义一个基类,构造其派生类,在构造函数中输出提示信息,观察构造函数的执行情况。 解:

#include

class BaseClass {

public:

BaseClass(); };

BaseClass::BaseClass() {

cout <<\构造基类对象!\ }

class DerivedClass : public BaseClass {

public:

DerivedClass(); };

DerivedClass::DerivedClass() {

cout <<\构造派生类对象!\}

void main() {

DerivedClass d; }

程序运行输出: 构造基类对象! 构造派生类对象!

6-4 定义一个Document类,有name成员变量,从Document派生出Book类,增加PageCount变量。 解:

#include #include

class Document {

public:

Document(){};

Document( char *name );

char *Name; // Document name. void PrintNameOf(); // Print name. };

Document::Document( char *name ) {

Name = new char[ strlen( name ) + 1 ]; strcpy( Name, name ); };

void Document::PrintNameOf() {

cout << Name << endl; }

class Book : public Document {

public:

Book( char *name, long pagecount ); void PrintNameOf(); private:

long PageCount; };

Book::Book( char *name, long pagecount ):Document(name) {

PageCount = pagecount; }

void Book::PrintNameOf() {

cout <<\Document::PrintNameOf(); }

void main() {

Document a(\Book b(\b.PrintNameOf(); }

程序运行输出: Name of book: Book1

6-5 定义基类Base,有两个共有成员函数fn1()、fn2(),私有派生出Derived类,如果想在Derived类的对象中使用基类函数fn1(),应怎么办? 解:

class Base {

public:

int fn1() const { return 1; } int fn2() const { return 2; } };

class Derived : private Base { public:

int fn1() { return Base::fn1();}; int fn2() { return Base::fn2();}; };

void main() {

Derived a; a.fn1(); }

6-6 定义object类,有weight属性及相应的操作函数,由此派生出box类,增加Height和width属性及相应的操作函数,声明一个box对象,观察构造函数与析构函数的调用顺序。 解:

#include class object {

private: int Weight; public: object()

{

cout <<\构造object对象\Weight = 0; }

int GetWeight(){ return Weight;} void SetWeight(int n){ Weight = n;}

~object() { cout <<\析构object对象\};

class box : public object {

private:

int Height,Width; public: box() {

cout <<\构造box对象\Height = Width = 0; }

int GetHeight(){ return Height;} void SetHeight(int n){ Height = n;} int GetWidth(){ return Width;} void SetWidth(int n){ Width = n;}

~box() { cout <<\析构box对象\};

void main() { box a; }

程序运行输出: 构造object对象 构造box对象 析构box对象 析构object对象

6-7 定义一个基类BaseClass,从它派生出类DerivedClass,BaseClass有成员函数fn1()、fn2(),DerivedClass也有成员函数fn1()、fn2(),在主程序中定义一个DerivedClass的对象,分别用DerivedClass的对象以及BaseClass和DerivedClass的指针来调用fn1()、fn2(),观察运行结果。 解:

#include

class BaseClass {

public: void fn1(); void fn2(); };

void BaseClass::fn1() {

cout <<\调用基类的函数fn1()\}

void BaseClass::fn2() {

cout <<\调用基类的函数fn2()\}

class DerivedClass : public BaseClass {

public: void fn1(); void fn2(); };

void DerivedClass::fn1() {

cout <<\调用派生类的函数fn1()\}

void DerivedClass::fn2() {

cout <<\调用派生类的函数fn2()\}

void main() {

DerivedClass aDerivedClass;

DerivedClass *pDerivedClass = &aDerivedClass; BaseClass *pBaseClass = &aDerivedClass;

aDerivedClass.fn1(); aDerivedClass.fn2(); pBaseClass->fn1(); pBaseClass->fn2(); pDerivedClass->fn1(); pDerivedClass->fn2(); }

程序运行输出:

调用派生类的函数fn1() 调用派生类的函数fn2() 调用基类的函数fn1() 调用基类的函数fn2() 调用派生类的函数fn1() 调用派生类的函数fn2()

6-8什么叫做虚基类?有何作用? 解:

当某类的部分或全部直接基类是从另一个基类派生而来,这些直接基类中,从上一级基类继承来的成员就拥有相同的名称,派生类的对象的这些同名成员在内存中同时拥有多个拷贝,我们可以使用作用域分辨符来唯一标识并分别访问它们。我们也可以将直接基类的共同基类设置为虚基类,这时从不同的路径继承过来的该类成员在内存中只拥有一个拷贝,这样就解决了同名成员的唯一标识问题。

虚基类的声明是在派生类的定义过程,其语法格式为: class 派生类名:virtual 继承方式 基类名 上述语句声明基类为派生类的虚基类,在多继承情况下,虚基类关键字的作用范围和继承方式关键字相同,只对紧跟其后的基类起作用。声明了虚基类之后,虚基类的成员在进一步派生过程中,和派生类一起维护一个内存数据拷贝。

6-9 什么叫做拷贝构造函数?拷贝构造函数何时被调用? 解:

拷贝构造函数是一种特殊的构造函数,具有一般构造函数的所有特性,其形参是本类的对象的引用,其作用是使用一个已经存在的对象,去初始化一个新的同类的对象。在以下三种情况下会被调用:在当用类的一个对象去初始化该类的另一个对象时;如果函数的形参是类对象,调用函数进行形参和实参结合时;如果函数的返回值是类对象,函数调用完成返回时; 6-10 拷贝构造函数与赋值运算符(=)有何不同? 解:

赋值运算符(=)作用于一个已存在的对象;而拷贝构造函数会创建一个新的对象。

第七章 函数重载

7.1、参考本例子,建立一个源程序文件,在此文件中建立一个新的类,将新建的类命名为Rect。 class Rect { public:

int Area_int(); double Area_double(); Rect(double l,double w); Rect(int l,int w); virtual ~Rect();

private: int nLength; int nWidth; double dLength; double dWidth; }; 实验要求:

(1)向Rect类中添加数据成员及成员函数,并完善成员函数的功能。如设计一个Area_int()函数,计算边长为整型的长方形的面积;设计一个Area_double()函数,计算边长为double型的长方形的面积。

(2)重载构造函数。一种构造函数用整型变量记录长方形的长和宽,另一种构造函数用double型记录。

(3)体现对象的构造和析构过程。例如,在构造函数中用cout<<”I am the constructor!”<

(4)在main()函数中定义两个Rect类的对象,一个对象用实例实现(就像定义普通的变量一样),另一个对象用指针实现(利用关键字new,给指针分配内存空间)。并用不同的参数,以调用不同的构造函数体现构造函数的重载。 #include using namespace std; class Rect {

public:

Rect(double l,double w) { dLength=l; dWidth=w; cout<<\ }

Rect(int l,int w) { nLength=l; nWidth=w; cout<<\ }

int Area_int() {

int Ai; Ai=nLength*nWidth; return Ai; }

double Area_double() { double Ad; Ad=dLength*dWidth; return Ad; }

virtual ~Rect() { cout<<\ } private:

int nLength; int nWidth; double dLength; double dWidth; };

void main() { Rect R1(1,2); cout<Area_double()<

int Ai; Ai=nLength*nWidth; return Ai; }

double Area_double() { double Ad; Ad=dLength*dWidth; return Ad; }

virtual ~Rect() { cout<<\ } private:

int nLength; int nWidth; double dLength; double dWidth; };

void main() { Rect R1(1,2); cout<Area_double()<

本文来源:https://www.bwwdw.com/article/d5ww.html

Top