第7章类与对象
1、什么叫面向对象的程序设计语言?什么叫类?什么叫对象?什么叫消息?
答:在程序设计语言中,面向对象是指采用抽象、封装、继承、多态等程序设计的方法。
因此,具有抽象、封装、继承、多态等特性的编程语言称为面向对象的程序设计语言。
类实际上是一种抽象的数据类型,它将完成某特定功能所用到的数据和对数据的操作(即函数)封装在一起。
对象是指具有某些属性和功能的单个个体。
消息是对象之间相互请求或相互协作的途径,是要求某个对象执行其中某个功能操作的规格说明。
2、结构化程序设计方法存在什么问题?
答:结构化程序设计方法主要存在以下问题:
1)软件重用性差:重用性是指同一软件不经修改或稍加修改就可多次重复使用的性质。
软件重用性是软件工程追求的目标之一。
2)软件可维护性差:软件工程强调软件的可维护性,强调文档资料的重要性,规定最终的软件产品应该由完整、一致的配置成分组成。
在软件开发过程中,始终强调软件的可读性、可修改性和可测试性是软件的重要的质量指标。
实践证明,用传统方法开发出来的软件,维护时其费用和成本仍然很高,其原因是可修改性差,维护困难,导致可维护性差。
3)开发出的软件不能满足用户需要:用传统的结构化方法开发大型软件系统涉及各种不同领域的知识,在开发需求模糊或需求动态变化的系统时,所开发出的软件系统往往不能真正满足用户的需要。
3、什么叫抽象?什么叫分类?
答:从许多事物中舍弃个别的、非本质的特征,抽取共同的、本质性的特征,就叫作抽象。
抽象是形成概念的必须手段。
分类就是把具有相同属性和服务的对象划分为一类,用类作为这些对象的抽象描述。
4、请简述结构体、联合体和类三种类类型的异同点。
答:三种类类型的异同点见下列表格:
struct结构体类型和class类类型都可以封装数据和操作,具有派生性、隐藏性和多态性。
而联合体不具有派生性,但具有隐藏性和多态性。
5、什么叫根类?
答:根类是没有从其它类派生而创建的类类型。
实际上,根据class类类型定义的一般形式,[:<基类型列表>]是一个可缺省的项;如缺省将定义一个根类。
6、类定义通常分为两部分,主要指什么?
答:类的定义一般分为说明部分和实现部分,说明部分放在类定义体内,用来说明该类中的数据成员和函数成员的类型和名称,是类的外部接口;实现部分常放在类体外,用以给出说明部分中声明的成员函数的定义,是类的内部实现。
7、在类定义中,说明成员的访问权限的public、private和protected三个关键字的作
用是什么?请分别简述之。
答:在类定义体里,使用了private、protected、public三个关键字是用来说明数据成员和函数成员的访问权限,private说明私有成员,该类成员只能被自己的成员函数或友元访问;protected说明保护型的成员,可以被自己的成员函数或友元访问,也可以被派生类的函数成员访问;public说明公有成员,该类成员都可以通过对象被访问的。
8、什么叫内联函数?什么叫外联函数?
答:将说明部分和成员函数实现部分合并在类定义体内,即将该函数定义为内联函数。
若该函数语句行不多且又无循环语句和开关语句也可以成为内联函数,只要在该函数的类型说明符之前使用关键字inline即可。
外联函数是指函数的说明放在类定义体内,而函数的定义是在类定义体外的类成员函数。
9、简述构造函数和析构函数的特点。
答:构造函数是类的成员函数,函数体可写在类定义体内,也可在类定义体外定义;它是一个特殊的函数,其函数名与类名相同,该函数不指定类型说明,它有隐含的返回值,该值由系统内部使用;该函数可以没有参数,也可以有一个或多个参数,即构造函数可以重载,可以定义具有不同数据类型或不同参数个数的构造函数;另外,程序中不能直接调用构造函数,在创建对象时系统将自动调用构造函数。
析构函数也是类中的成员函数,其定义的函数体可写在类定义体内,也可在类定义体外;它也是一个特殊的函数,它的名字与类名相同,但在其前面要加上“~”字符,用来区别于构造函数;析构函数也不指定数据类型,并且也没有形式参数;但一个类中只可以定义一个
析构函数;析构函数还可以被调用,也可以被系统自动调用。
10、为什么要用拷贝构造函数?它有哪些特点?
答:拷贝构造函数是一种特殊的构造函数,它的功能是用一个已有数值的对象赋值给另一个同类的一个对象。
拷贝构造函数是构造函数,但它是在赋值时被调用,将一个已有数值的对象的数据成员的值拷贝给另一个同类的对象的对应数据成员。
拷贝构造函数的特点如下:
(1)该函数名同类名,因为它也是一种构造函数,并且该函数也不被指定返回类型;
(2)该函数只有一个参数,并且是对同类的某个对象的引用;
(3)每个类都必须有一个拷贝构造函数;
(4)在新建对象时,对对象进行初始化时调用,对象之间赋值不调用。
11、简述深拷贝和浅拷贝。
答:如果一个类的数据成员需要使用动态分配的堆资源,并且这个类的对象之间发生了数据成员拥有的堆资源复制过程的时候,这个过程就可以叫做深拷贝,反之,对象存在数据成员拥有堆资源但复制过程并未实现数据成员拥有堆资源的复制情况视为浅拷贝。
12、this指针有什么作用?
答:this是专门指向类对象自身的地址常量,是一个隐含式的指针,也就是说使用它时不需要自己去定义就可使用,而是由系统自己设定的。
另外,它也隐含于每一个成员函数中,也就是说类的每一个成员函数都有一个this指针,它指向了该函数所属类的对象。
this是指向对象自己的指针,* this 就是对象自己。
this指针只能在某一个类的函数体内使用,其他地方无意义。
该指针指向类的一个实例,实际上,该指针指向当前正在操作的应用对象自身。
13、简述类中使用常对象和常成员函数需要注意的问题。
答:使用常对象和常成员函数需要注意以下问题:
(1)常对象在说明时必须进行初始化,而且不能被更新。
常对象还可以作为类的成员。
(2)const是函数类型的一个组成部分,因此在函数实现部分也要带有const关键字;
(3)在常成员函数里不能更改所属类的数据成员,也不能调用该类中没有用const修饰的类的成员函数;
(4)常对象只能调用它的常成员函数,而不能调用其他的成员函数;
(5)const关键字可以用于进行函数重载的区分。
其重载的原则是:常对象只能调用常成
员函数,一般对象调用一般成员函数。
14、答:
class CTest
{
int 【1】num ;
float f1;
public:
CTest(int n, float f);
CTest(CTest& t) ;
};
CTest::CTest(【2】int n, float f )
{ num = n;
【3】f1 = f;
}
CTest::CTest(【4】CTest& t )
{ num= 【5】t.num ;
f1 = t. f1;
}
15、答:
class CString
{
public:
CString(short = 0);
CString(const char*);
CString(const string&);
~CString{delete[] pStr;}
int length() const {return len;}
char* convert() {return pStr;}
char character(short i) {char c=pStr[i]; return c;}
void print() {cout << pStr;}
private:
short len;
char* pStr;
};
CString::CString(short size):len(size)
{
pStr=new char[len+1];
for(int i=0;i<len;i++) pStr[i]='';
pStr[len]='\0';
}
CString::CString(const char* str):len(strlen(str)) {
pStr=new char[len+1];
memcpy(pStr,str,len+1);
}
CString::CString(const CString& str):len(str.len) {
pStr=new char[len+1];
memcpy(pStr,str.pStr,len+1);
}。