资源描述
判断题:1×10分
1. 面向对象的程序设计具有如下的几大基本特征,它们是抽象、 封装 、继承 、多态 。
2. 抽象是指从众多的事物中抽取出共同的、本质性的特征,而舍弃其非本质的特征。
3. 类的封装性是指数据(数据成员)与操作(成员函数)紧密结合,构成一个不可分割的整体(对象),并且以不同的访问控制方式(private,protected,public)对这些成员作出限定。
4. 由同一个类可以定义出不同的对象,不同对象的数据成员是不同的,所以各对象的数据成员在内存中占据不同的内存空间(静态数据成员例外,它存放在类的公用区;但同一个类的不同对象的成员函数的代码都是相同的,所以各对象的成员函数只需要在内存中(类的公用区)存放一份代码,供大家共用。
5. 同一个类的不同对象共用同一份成员函数的代码,是C++为了节省内存而采用的对象存储方式,在逻辑上我们仍然应该将每一个对象看作是独立的、不同的个体,每个对象都有自己的数据成员和成员函数。
6. 构造函数也是一种成员函数;构造函数的函数名必须和它所在类的类名相同;构造函数没有返回值,当然也就没有返回类型,即使是void类型也不允许使用;一个类可以有多个构造函数,即构造函数可以被重载;构造函数是在创建对象时被系统自动调用的,而不是通过“.”显示调用的,这也是和一般成员函数在使用上非常明显的区别。
7. 析构函数也是一种成员函数;析构函数的函数名必须使用它所在类的类名,且前面加上一个波浪号;析构函数没有返回值和返回类型,且没有任何参数;一个类只能有一个析构函数,即析构函数不能被重载;析构函数多数情况是在对象生存期结束时由系统自动调用的,少数情况下也可以在用户代码中通过“.”显示调用。
8. 一个类的友元函数并不是该类的成员,所以不能通过该类的对象来访问,也不能被该类的子类所继承。
9. 对于从父类继承来的成员,它们在派生类中的访问控制方式要由父类成员的访问控制方式和派生类定义时的访问说明来共同决定。
10. 在公有派生的情况下,基类成员在派生类中的访问权限保持不变。
11. 在C++中,函数的参数有两种传递方式,一种是值传递方式,另一种是指针(地址)或 引用 传递方式。
12. 当一个成员函数被调用时,该成员函数的 this 指针指向调用它的对象。
13. 异常处理是指程序设计语言提供的一种用于管理程序运行期间出现异常的机制。异常处理可以提高程序的健壮性。C++语言将程序中的异常处理设计为两个过程:异常的检测和异常的处理。
14. 异常检测部分在检测到某个异常后可以使用throw语句抛出该异常。异常被抛出以后,需要有相关的异常处理代码对其进行捕获和处理,如果程序代码中没有给出相应的异常处理代码,系统将自动调用标准库函数terminate,terminate默认调用标准库函数abort,导致程序终止。
15. 动态联编要满足两个条件,一个是被调用的成员函数必须是虚函数,另一个是必须用指针或引用调用该虚函数。
16. 从系统实现角度来看,多态性包括静态多态性(编译时多态性)和动态多态性(运行时多态性)两大类。
17. 静态多态性是指通过函数重载和类属机制来实现的。在程序编译时系统就能确定调用哪个函数,因此静态函数又称编译时的多态性。例如:函数重载和运算符重载就属于这种情况。
18. 动态多态性是指通过虚函数、继承机制,以及动态绑定机制来实现的。在程序运行过程中才动态地确定操作指针所指的对象,主要通过虚函数和重写来实现。
19. 引用在创建的同时必须进行初始化,即引用到一个有效的对象;而指针在定义的时候不必立即初始化,可以在定义之后的任何地方给它赋值。引用一旦被初始化为指向一个对象以后,它就不能被改变为另一个对象的引用;而指针在任何时候都可以被改变为指向另一个对象。不存在指向空值的引用,但是存在指向空值的指针。
20. 在C++中有一种不能定义对象的类,它只能被继承,这种类称为抽象类,抽象类在定义时至少要有一个纯虚函数。
21. 在C++类中,const关键字可以修饰对象和成员函数,const对象不能被修改,const成员函数不能修改其所在类中的数据成员。
22. 没有定义在类中的函数,都称为全局函数。
23. 定义在类中的函数,称为成员函数,其作用域在该类的内部,它可以访问该类中的所有成员(包括公有的、保护的、私有的所有数据成员和成员函数)。
24. 如果要把一个函数fun(可以是全局函数或类的成员函数)定义为类A的一个友元函数,则需要在类A中用保留字friend来说明,但该友元函数fun并不是类A的成员,所以对fun的定义自然应该在类A的外面。函数fun被定义为类A的友元函数以后,fun就可以像是类A的成员函数那样访问类A的成员了。
25. 运行时多态性的基础是共有派生类对基类类型的兼容性,即指向基类对象的指针可以指向该基类的公有派生类对象,类似地,基类对象的引用也可以关联到该基类的公有派生类对象。
找错题:
1、以下程序中哪些语句是错误的?请用双斜线将它们注解掉。
#include "iostream.h"
void main()
{
const int a1=7;
int const a2=8;
int c1=9;
int c2=10;
const int *d1=&a1;
const int *d2=&c1;
int const* e1=&a1;
int const* e2=&c1;
e2=e1;
// *e2=33;
int * const f1=&c1;
int * const f2=&c2;
// int * const f3=&a1;
// f2=f1;
*f2=33;
const int * const g1 =&a2;
const int * const g2 =&c2;
// g2=g1;
// *g2=33;
*f1=*g1;
cout<<"a1="<<a1<<",a2="<<a2<<",c1="<<c1<<",c2="<<c2<<endl;
cout<<"d1="<<*d1<<",d2="<<*d2<<endl;
cout<<"e1="<<*e1<<",e2="<<*e2<<endl;
cout<<"f1="<<*f1<<",f2="<<*f2<<endl;
cout<<"g1="<<*g1<<",g2="<<*g2<<endl;
}
分析:
其中,a1和a2都是整型常量,c1和c2都是整型变量,d1、d2、e1、e2都是指向整型数据(既可以是整型常量也可以是整型变量)的指针变量,f1、f2、f3都是指向整型变量的指针常量,g1和g2都是指向整型数据的指针常量。需要特别强调的是,虽然d2、e2、g2都可以指向一个整型变量,但这并不等于说就可以通过这些指针去修改那些整型变量,因为有const的保护,所以是不能去修改那些受保护的整型数据的。
保留字const的作用是:
1).要向阅读代码的人和编译器明确传达一个非常重要的信息,就是哪些内容是“受保护的”,即不能被修改。这既可以增强程序的可读性,又可以增强程序的健壮性,减少bug的出现。
2)const除了可以用来定义常量以外,还可以用来修饰函数的参数、返回值,甚至函数的定义体。被 const 修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。
3). 通过给优化器一些附加的信息,使用保留字const也许能产生更紧凑的代码。
2、以下程序中哪些语句是错误的?请用双斜线将它们注解掉。
#include <iostream.h>
#include <string.h>
class stud // 定义基类
{
private: // 基类私有成员
int num;
char name[30];
char sex;
protected: // 基类保护成员
char major[15];
public: // 基类公有成员
stud( int n, char nam[], char s, char maj[] )
{
num=n;
strcpy( name, nam);
sex=s;
strcpy(major, maj);
}
void display( )
{
cout<<"num:"<<num<<endl;
cout<<"name:"<<name<<endl;
cout<<"sex:"<<sex<<endl;
cout<<"major:"<<major<<endl<<endl; // 访问本类保护成员
}
};
class student: public stud // 定义一个公有派生类
{
private:
int age;
char addr[50];
public:
void show( )
{
display( ); // 引用基类的公有成员函数
// cout<<"num:"<<num<<" name:"<<name <<" sex:"<<sex <<endl;
// ×企图引用基类的私有成员
cout<<"age:"<<age<<endl; // 引用派生类的私有成员
cout<<"address:"<<addr<<endl; // 引用派生类的私有成员
strcpy(major, "Computer Science");
cout<<"major:"<<major<<endl<<endl;
}
// student( int n, char nam[], char s, char maj[],int age1=20):stud(n,s,nam,maj) //与基类构造函数的参数顺序不对应
{
age=age1;
strcpy(addr, "四川理工学院");
}
};
void main()
{
student a(2, "Zhang_Yang", 'M', "applications math"); // 定义了一个派生类对象
a.display( ); // 以上两句,调用从基类继承来的共有成员函数
a.show(); // 调用派生类自己定义的共有成员函数
// a.num=10020; // ×企图从外界引用基类的私有成员
// a.age=18; // ×企图从外界引用派生类的私有成员
}
选择题:2×10分
1. 使用值传递方式将实参传给形参,下列说法正确的是( A )。
A.形参是实参的备份 B.实参是形参的备份
C.形参和实参是同一对象 D.形参和实参无联系
2. 下面是对C++中static保留字的叙述,错误的是(D)。
A) 在函数体中,一个被声明为静态的变量在这个函数被调用结束以后,它依然存在且保留调用结束时的值。
B) 在源文件内(但在函数体外),一个被声明为静态的变量可以被该源文件内所有的函数访问,但不能被该源文件外的其它函数访问。它是一个本地的全局变量。
C) 在源文件内,一个被声明为静态的函数只可被这一源文件内的其它函数调用。那就是,这个函数被限制在声明它的源文件的本地范围内使用。
D) 一个变量只有被声明为static以后才是静态存储的,生存期才是整个程序的运行期。
3. 在C++语言中,数据封装要解决的问题是(D)
A.数据的规范化 B.便于数据转换
C.避免数据丢失 D.防止不同模块之间数据的非法访问
4. 下同对静态数据成员的描述中,正确的是(A)
A.静态数据成员是类的所有对象共享的数据
B.类的每个对象都有自己的静态数据成员
C.类的不同对象有不同的静态数据成员值
D.静态数据成员不能通过类的对象调用
5. 下面关于虚函数的描述,错误的是(D )
A.在成员函数声明的前面加上virtual修饰,就可把该函数声明为虚函数
B.基类中说明了虚函数后,派生类中对应的函数也必须说明为虚函数
C.虚函数可以是另一个类的友元函数,但不能是静态成员函数
D.基类中说明的纯虚函数在其任何派生类中都必须实现
6. int Func(int,int);不可与下列哪个函数构成重载(B 不可能返回double型数值 )
A.int Func(int,int,int); B.double Func(int,int);
C.double Func(double,double); D.double Func(int,double);
7. 下列关于构造函数的描述中,错误的是(D)
A)构造函数可以设置默认参数; B)构造函数在定义类对象时自动执行
C)构造函数可以是内联函数; D)构造函数不可以重载
8. 下列关于构造函数的描述中,正确的是(B)
A) 一个类中的构造函数不能被重载
B) 任何一个类都必定会有一个构造函数
C) 任何一个类都必定会有一个默认构造函数
D) 任何一个类都必须自己定义一个构造函数
9. 下面描述中,表达错误的是(A)
A)公有派生时基类中的private成员在派生类中仍是private的
B)公有派生时基类中的protected成员在派生类中仍是protected的
C)公有派生时基类中的public成员在派生类中仍是public的
D)私有派生时基类中的public成员在派生类中是private的
10. C++中运算符重载可以实现改变()
A) 运算符的优先级
B) 运算符的结合性
C) 运算符的操作数个数
D) 运算符的功能
11. 只能作为成员函数重载的是(A)
A.= B.++ C.* D.new
12. 下列运算符中,在C++语言中不能重载的是(C)。
A)* B)>= C):: D)/
13. 以下关于基类指针和派生类指针的叙述中不正确的是()
A) 基类指针可以指向它的公有派生类的对象
B) 基类指针可以指向它的多次派生后的派生类的对象
C) 派生类的指针不能指向基类的对象
D) 基类指针可以指向它的所有派生类的对象,并通过该基类指针可以访问到派生类对象的所有成员。
14. 以下关于友元函数的叙述中,正确的是(B)
A) 友元函数不能访问类的私有成员
B) 友元函数破坏了类的封装性和隐藏性
C) 友元函数的使用与类的成员函数相同
D) 友元函数的实现必须在类的说明中定义
15. 多态性指的是(C )
A.以任何方式调用一个虚函数
B.以任何方式调用一个纯虚函数
C.借助于指向对象的基类指针或引用调用一个虚函数
D.借助于指向对象的基类指针或引用调用一个纯虚函数
16. 当使用ifstream流类定义一个流对象并打开一个磁盘文件时,文件的隐含打开方式为( A )。
A:ios::in B:ios::out C:ios::in | ios::out D:ios::binary
17. 语句ofstream f(″SALARY.DAT″,ios::app|ios::binary);的功能是建立流对象f,试图打开文件SALARY.DAT并与之连接,并且( A )
A.若文件存在,将文件写指针定位于文件尾;若文件不存在,建立一个新文件
B.若文件存在,将其置为空文件;若文件不存在,找开失败
C.若文件存在,将文件写指针定位于文件首;若文件不存在,建立一个新文件
D.若文件存在,找开失败;若文件不存在,建立一个新文件
18. 在结构体中定义的成员,若不做明确指明,其隐含访问权限为___C __。
A. private B. protected C. public D. static
19. 下列说法正确的是(B)。
A)内联函数在运行时是将该函数的目标代码插入每个调用该函数的地方
B)内联函数在编译时是将该函数的月标代码插入每个调用该函数的地方
C)类的内联函数必须在类体内定义
D)类的内联函数必须在类体外通过加关键字inline定义
20. 下面对静态数据成员的描述中,正确的是(D)。
A)静态数据成员可以在类体内进行初始化
B)静态数据成员不可以被类的对象调用
C)静态数据成员不能受private控制符的作用
D)静态数据成员可以直接用类名调用
21. 在公有派生情况下,有关派生类对象和基类对象的关系,下列叙述不正确的是(C)。
A)派生类的对象可以赋给基类的对象
B)派生类的对象可以初始化基类的引用
C)派生类的对象可以直接访问基类中的成员
D)派生类的对象的地址可以赋给指向基类的指针
22. 下面程序的运行结果为(C)。
#include<iostream. h>
class A
{
public:
A(){cout<<”1”;}
~A(){cout<<”2”;}
}
class B:public A
{
public:
B(){cout<<”3”;}
~B(){cout<<”4”;}
}
void main()
{
B b;
}
A)1234 B)1324 C)1342 D)3142
23. 下列关于虚基类的描述,错误的是(B)。
A)设置虚基类的目的是为了消除多重继承中的一种二义性问题(重复继承问题)
B)虚基类的构造函数在非虚基类之后调用
C)若同一层中包含多个虚基类,这些虚基类的构造函数按它们说明的次序调用
D)若虚基类由非虚基类派生而来,则仍然先调用基类构造函数,再调用派生类的构造函数
24. 下列关于多态性的描述,错误的是(C)。
A)C++语言的多态性分为编译时的多态性和运行时的多态性
B)编译时的多态性可通过函数重载实现
C)运行时的多态性可通过模板和虚函数实现
D)实现运行时多态性的机制称为动态绑定
25. 当使用fstream流类定义一个流对象并打开一个磁盘文件时,文件的隐含打开方式为(D)。
A)ios::in
B)ios::out
C)ios::in|ios::out
D)以上都不对
26. 下列程序的运行结果是(B)。
#include<iostream.h>
class A
{
int a;
public:
A(){a=0;}
A(int as)
{
a=as;
cout<<a++<<",";
}
};
void main()
{
A x,y(3),z(5);
cout<<endl;
}
A) 0 3 5 B) 3,5, C) 0,3,5, D) 3 5
程序填空题:3×15分
1. 以下程序的功能是:求圆、或圆的内接正方形、或圆的外切正方形的面积与周长。请完成程序。
#include <iostream.h>
const double PI=3.1415;
class Shape
{
public:
Shape(double i)
{ r=i; }
virtual void Area()=0;
virtual void Perimeter()=0;
protected:
double r;
};
class Circle:public Shape
{
public:
Circle(double i):Shape(i)
{ }
void Area()
{ cout<<"圆的面积是 "<<PI*r*r<<endl; }
void Perimeter()
{ cout<<"圆的周长是 "<<2*PI*r<<endl; }
};
class In_Square:public Shape
{
public:
In_Square(double i):Shape(i)
{ }
void Area()
{ cout<<"圆内接正方形的面积是 "<<2*r*r<<endl; }
void Perimeter()
{ cout<<"圆内接正方形的周长是 "<<4*1.414*r<<endl; }
};
class Ex_Square:public Shape
{
public:
Ex_Square(double i):Shape(i)
{ }
void Area()
{ cout<<"圆外切正方形的面积是 "<<4*r*r<<endl; }
void Perimeter()
{ cout<<"圆外切正方形的周长是 "<<8*r<<endl; }
};
void main()
{
Shape *ps;
ps=new Circle(8);
ps->Area();
ps->Perimeter();
delete ps;
ps=new In_Square(8);
ps->Area();
ps->Perimeter();
delete ps;
ps=new Ex_Square(8);
ps->Area();
ps->Perimeter();
delete ps;
}
2. 以下程序的功能是:求解一元二次方程的根,其中实现了一个Complex复数类和一个Real实数类,Real类定义为Complex类的子类;另外还实现了一个Root类,完成求解一元二次实系数方程的根。请完成程序。
#include <iostream.h>
#include <iomanip.h>
#include <math.h>
class Complex
{
public:
Complex(double r=0,double i=0)
{
re=r;
im=i;
}
virtual void Print();
protected:
double re,im;
private:
};
class Real:public Complex
{
public:
Real(double r=0):Complex(r,0)
{
}
void Print()
{
cout<<re;
}
protected:
private:
};
class Root
{
public:
Root(double m1,double m2,double m3)
{
a=m1;
b=m2;
c=m3;
}
void Print();
void Solve();
protected:
double a,b,c;
private:
};
void Complex::Print()
{
cout<<"("<<re<<","<<im<<"i)";
}
void Root::Print()
{
cout<<"方程";
cout<<a;
cout<<setiosflags(ios::showpos);
cout<<"*X*X";
cout<<b<<"*X";
cout<<c<<"=0\n";
cout<<resetiosflags(ios::showpos);
}
void Root::Solve()
{
Print();
cout<<"的解是:"<<endl;
double delta=b*b-4*a*c;
if(fabs(delta)<1e-5)
{
Real x(-b/2/a);
cout<<"\nX1=X2=";
x.Print();
cout<<endl;
}
else if (delta>0)
{
Real x1(-b/2/a+sqrt(delta)/2/a);
Real x2(-b/2/a-sqrt(delta)/2/a);
cout<<"\nX1=";
x1.Print();
cout<<"\nX2=";
x2.Print();
}
else
{
Complex x1(-b/2/a,sqrt(-delta)/2/a);
Complex x2(-b/2/a,-sqrt(-delta)/2/a);
cout<<"\nX1=";
x1.Print();
cout<<"\nX2=";
x2.Print();
cout<<endl;
}
}
void main()
{
double a,b,c;
cout<<"\n请输入一元二次方程的三个系数a,b,c: ";
cin>>a>>b>>c;
Root rot (a,b,c);
rot.Solve();
}
3. 以下程序的功能是:用类成员函数重载“+”、“-”两个双目运算符,使之可以用于复数的运算。请完成程序。
#include<iostream>
using namespace std;//可用#include<iostream.h>来替换这两行
class complex //复数类声明
{
public: //外部接口
complex(double r=0.0,double i=0.0)
{
real=r;imag=i;
}
complex operator+ (complex c2); //+重载为成员函数
complex operator- (complex c2); //-重载为成员函数
void display(); //输出复数
private: //私有数据成员,自己内部使用
double real; //复数实部
double imag; //复数虚部
};
complex complex::operator+(complex c2)
{
complex c;
c.real=c2.real+real;
c.imag=c2.imag+imag;
return complex(c.real,c.imag);
}
complex complex::operator-(complex c2)
{
complex c;
c.real=real-c2.real;
c.imag=imag-c2.imag;
return complex(c.real,c.imag);
}
void complex::display()
{
cout<<real<<"+("<<imag<<")i"<<endl;
}
void main()
{ complex c1(2,3),c2(6,8),c3; //声明复数类的对象
cout<<"c1="; c1.display();
cout<<"c2="; c2.display();
c3=c1-c2; //使用重载运算符完成复数减法
cout<<"c3=c1-c2=";
c3.display();
c3=c1+c2; //使用重载运算符完成复数加法
cout<<"c3=c1+c2=";
c3.display();
}
运行结果:
c1=2+(3)i
c2=6+(8)i
c3=c1-c2=-4+(-5)i
c3=c1+c2=8+(11)i
4. 以下程序的功能是:用类成员函数分别重载单目运算符“++” 的前置和后置用法,使之可以用于时间的运算,不断地增加1秒。请完成程序。
#include<iostream>
using namespace std;
class Clock //定义一个时钟类
{
public:
Clock(int NewH=0, int NewM=0, int NewS=0);
void ShowTime();
Clock& operator++(); //前置单目运算符重载
Clock operator++(int); //后置单目运算符重载
private:
int Hour,Minute,Second;
};
Clock& Clock::operator ++()
//前置单目运算符重载函数
{ Second++;
if(Second>=60)
{ Second=Second-60;
Minute++;
if(Minute>=60)
{
Minute=Minute-60;
Hour++;
Hour=Hour%24;
}
}
return *this; //将这个被前置运算后的对象通过引用返回
}
Clock Clock::operator ++(int)
//后置单目运算符重载函数
//注意形参表中的这个int参数,可以不写形参名,写了也不用
{
Clock old=*this;
++(*this); //调用前置单目运算符重载函数
return old;
}
//其它成员函数的实现
Clock::Clock(int NewH, int NewM, int NewS)
{
Hour=NewH; Minute=NewM; Second=NewS;
}
void Clock::ShowTime()
{
cout<<Hour<<":"<<Minute<<":"<<Second<<endl;
}
void main()
{
Clock myClock(23,59,59);
cout<<"Time:";
myClock.ShowTime();
cout<<"Show ++Time:";
(++myClock).ShowTime();
cout<<"Show Time++:";
(myClock++).ShowTime();
}
运行结果:
Time:23:59:59
Show ++Time:0:0:0
Show Time++:0:0:0
5. 以下程序的功能是:用友元函数重载“+”、“-”两个双目运算符,使之可以用于复数的运算。请完成程序。
#include<iostream.h>
class complex
{
public:
complex(double r=0.0,double i=0.0)
{ real=r; imag=i; }
friend complex operator+(complex c1,complex c2); //运算符+被重载为本类的友元函数
friend complex operator-(complex c1,complex c2); //运算符-被重载为本类的友元函数
void display(); //显示复数的值
private: //私有数据成员
double real;
double imag;
};
complex operator+(complex c1,complex c2)
//友元函数实现运算符重载
{ return complex(c2.real+c1.real, c2.imag+c1.imag);
}
complex operator-(complex c1,complex c2)
//友元函数实现运算符重载
{ return complex(c1.real-c2.real, c1.imag-c2.imag);
}
void complex::display()
{
cout<<real<<"+("<<imag<<")i"<<endl;
}
void main()
{ complex c1(2,3),c2(6,8),c3; //声明复数类的对象
cout<<"c1="; c1.display();
cout<<"c2="; c2.display();
c3=c1-c2; //使用重载运算符完成复数减法
cout<<"c3=c1-c2=";
c3.display();
c3=c1+c2; //使用重载运算符完成复数加法
cout<<"c3=c1+c2=";
c3.display();
}
运行结果:
c1=2+(3)i
c2=6+(8)i
c3=c1-c2=-4+(-5)i
c3=c1+c2=8+(11)i
6. 以下程序的功能是:从键盘上录入一个输入文件名和一个输出文件名,然后程序将把输入文件中的内容全部拷贝到输出文件中。请完成程序。
#include <fstream.h>
int main()
{
char c;
char inFileName[50],outFileName[50];
ifstream inFile;
ofstream outFile;
cout<<"inFileName:";
cin>>inFileName;
cout<<"outFileName:";
cin>>outFileName;
inFile.open(inFileName);
outFile.open(outFileName);
inFile.get(c);
while(inFile)
{
outFile<<c;
inFile.get(c);
}
inFile.close();
outFile.close();
return 0;
}
7.
展开阅读全文