资源描述
资料内容仅供您学习参考,如有不当或者侵权,请联系改正或者删除。
第一章: 面向对象程序设计概述
[1_1]什么是面向对象程序设计?
面向对象程序设计是一种新型的程序设计范型。这种范型的主要特征是:
程序=对象+消息。
面向对象程序的基本元素是对象, 面向对象程序的主要结构特点是: 第一: 程序一般由类的定义和类的使用两部分组成, 在主程序中定义各对象并规定它们之间传递消息的规律。第二: 程序中的一切操作都是经过向对象发送消息来实现的, 对象接受到消息后, 启动有关方法完成相应的操作。
面向对象程序设计方法模拟人类习惯的解题方法, 代表了计算机程序设计新颖的思维方式。这种方法的提出是软件开发方法的一场革命, 是当前解决软件开发面临困难的最有希望、 最有前途的方法之一。
[1_2]什么是类? 什么是对象? 对象与类的关系是什么?
在面向对象程序设计中, 对象是描述其属性的数据以及对这些数据施加的一组操作封装在一起构成的统一体。对象能够认为是: 数据+操作
在面向对象程序设计中, 类就是具有相同的数据和相同的操作的一组对象的集合, 也就是说, 类是对具有相同数据结构和相同操作的一类对象的描述。
类和对象之间的关系是抽象和具体的关系。类是多个对象进行综合抽象的结果, 一个对象是类的一个实例。
在面向对象程序设计中, 总是先声明类, 再由类生成对象。类是建立对象的”摸板”, 按照这个摸板所建立的一个个具体的对象, 就是类的实际例子, 一般称为实例。
[1_3]现实世界中的对象有哪些特征? 请举例说明。
对象是现实世界中的一个实体, 其具有以下一些特征:
( 1) 每一个对象必须有一个名字以区别于其它对象。
( 2) 需要用属性来描述它的某些特性。
( 3) 有一组操作, 每一个操作决定了对象的一种行为。
( 4) 对象的操作能够分为两类: 一类是自身所承受的操作, 一类是施加于其它对象的操作。例如: 雇员刘名是一个对象
对象名: 刘名
对象的属性:
年龄: 36 生日: 1966.10.1 工资: 部门: 人事部
对象的操作: 吃饭 开车
[1_4]什么是消息? 消息具有什么性质?
在面向对象程序设计中, 一个对象向另一个对象发出的请求被称为”消息”。当对象接收到发向它的消息时, 就调用有关的方法, 执行相应的操作。消息是一个对象要求另一个对象执行某个操作的规格的说明, 经过消息传递才能完成对象之间的相互请求或相互协作。消息具有以下3个性质:
( 1) 同一个对象能够接收不同形式的多个消息, 做出不同的响应。
( 2) 相同形式的消息能够传递给不同的对象, 所做出的响应能够是不同的。
( 3) 消息的发送能够不考虑具体的接收者, 对象能够响应消息, 也能够不响应。
[1_5]什么是方法? 消息和方法的关系是什么?
在面向对象程序设计中, 要求某一对象作某一操作时, 就向该对象发送一个响应的消息, 当对象接收到发向它的消息时, 就调用有关的方法, 执行响应的操作。方法就是对象所能执行的操作。方法包括界面和方法体两部分。方法的界面也就是消息的模式, 它给出了方法的调用协议; 方法体则是实现某种操作的一系列计算步骤, 也就是一段程序。在C++语言中方法是经过函数来实现的, 称为成员函数。消息和方法的关系是: 对象根据接收到的消息, 调用相应的方法; 反过来, 有了方法, 对象才能响应相应的消息。
[1_6]什么是封装和抽象? 请举例说明。
在现实世界中, 所谓封装就是把某个事物包围起来, 使外界不知道该事物的具体内容。在面向对象程序设计中, 封装是指把数据和实现操作的代码集中起来放在对象内部, 并尽可能隐蔽对象的内部细节。对象好象是一个不透明的黑盒子, 表示对象属性的数据和实现各个操作的代码都被封装在黑盒子里, 从外面是看不见的, 更不能从外面直接访问或修改这些数据及代码。使用一个对象的时候, 只需要知道它向外界提供的接口形式而无需知道它的数据结构细节和实现操作的算法。封装机制能够将对象的使用者与设计者分开, 使用者不必知道对象行为实现的细节, 只需要使用设计者提供的接口让对象去做。
抽象是人类认识问题的最基本的手段之一。它忽略了一个主题中与当前目标无关的那些方面, 以便更充分地注意与当前目标有关的方面。抽象是对复杂世界的简单表示, 抽象强调感兴趣的信息, 忽略了不重要的信息。例如, 设计一个学籍管理程序的过程中, 考察某个学生对象时, 只关心她的姓名、 学好、 成绩等, 而对她的身高、 体重等信息就能够忽略。以一般观点而言, 抽象是经过特定的实例( 对象) 抽象共同性质以后形成概念的过程。抽象是对系统的简化描述或规范说明, 它强调了系统中的一部分细节和特性, 而忽略了其它部分。抽象包括两个方面: 数据抽象和代码抽象( 或称为行为抽象) 。前者描述某类对象的属性或状况, 也就是此类对象区别于彼类对象的特征物理量; 后者描述了某类对象的共同行为特征或具有的共同操作。
在面向对象程序设计方法中, 对一个具体问题的抽象分析的结果, 是经过类来描述和实现的。现在以学生管理程序为例, 经过对学生进行归纳、 分析, 抽取出其中的共性, 能够得到如下的抽象描述:
共同的属性: 姓名、 学号、 成绩等, 她们组成了学生数据抽象部分。用C++语言的数据成员来表示, 能够是:
char *name; int number; float score;
共同的行为: 数据录入、 数据修改和数据输出等, 这构成了学生的行为抽象部分, 用C++语言的成员函数表示, 能够是: input();modify();print(); 如果我们开发一个学生健康档案程序, 所关心的特征就有所不同了。可见, 即使对同一个研究对象, 由于所研究问题的侧重点不同, 就可能产生不同的抽象结果。
[1_7]什么是继承? 请举例说明。
继承所表示的是对象类之间的相关关系, 这种关系使得某类对象能够继承另一类对象的特征和能力。现实生活中, 继承是很普遍和容易理解的。例如我们继承了父母的一些特征, 如种族、 血型、 眼睛的颜色等, 父母是我们所具有的属性的基础。继承所表示的是对象之间相关的关系。这种关系使得某一类能够继承另一个类的特征和能力。
[1_8]若类之间具有继承关系, 则它们之间具有什么特征?
( 1) 类间具有共享特征( 包括数据和操作代码的共享)
( 2) 类间具有差别或新增部分( 包括非共享的数据和代码操作)
( 3) 类间具有层次结构
假设有两个类A和B, 若类B继承类A, 则类B包含了类A的特征( 包括数据和操作) , 同时也能够加入自己所特有的新特性。这时, 我们称被继承类A为基类或父类或超类; 而称继承类B为A类的派生类或子类。同时, 我们还能够说, 类B是从类A中派生出来的。
[1_9]什么是单继承、 多继承? 请举例说明。
从继承源上分, 继承分为单继承和多继承。单继承是指每个派生类只直接继承了一个基类的特征。多继承是指多个基类派生出一个派生类的继承关系。多继承的派生类直接继承了不止一个基类的特征。例如: 小孩的玩具车继承了车的一些特性, 还继承了玩具的一些特征。
[1_10]什么是多态性? 举例说明。
多态性也是面向对象程序设计的重要特性。它是指不同的对象收到相同的消息时产生不同的行为方式。例如我们同样双击windows系统桌面上的图标时, 有的是打开多媒体播放器, 有的是打开资源管理器。利用多态性, 用户只需发送一般形式的消息, 而将所有的实现留给接收消息的对象。对象根据所收到的消息做出相应的动作。
[1_11]什么是函数重载和运算符重载? 为什么要使用重载?
重载一般包括函数重载和运算符重载。函数重载是指一个表示符可同时用于为多个函数命名, 而运算符重载是指一个运算符可同时用于多种运算。也就是说, 相同名字的函数或运算符在不同的场合能够表现出不同的行为。
使用重载的目的是为了更好地表示行为共享, 这种行为共享就象将相似的操作划分在一起。使用重载能够使程序员在只知道操作的一般含义, 而不知道操作的具体细节的情况下能正确地对某个对象使用一个操作。另外, 使用重载的直接益处是减少了程序员记忆操作的名字的负担。
第二章:: C++基础
[2_1]简述C++的主要特点
( 1) C++保持与C的兼容, 用C编写的软件能够用到C++中。
( 2) 用C++编写的程序可读性好, 代码结构更合理, 可直接地在程序中映射问
题空间的结构。
( 3) 生成代码的质量高。
( 4) 软件的可重用性、 可扩充性、 可维护性和可靠性有了明显的提高, 从而节省了开发费用和时间。
( 5) 支持面向对象的机制, 可方便地构造出模拟现实问题的实体和操作。
[2_2]下面是一个C程序, 改写它, 使它采用C++风格的i/o语句
改写如下:
#include <iostream.h>
main()
{ int a,b,d,min;
cout<<”enter two numbers: ”;
cin>>a;
cin>>b;
min=a>b?b:a;
for(d=2;d<min;d++)
if((a%b)==0)&&((b%d)==0)) break;
if(d==min)
{ cout<<”no common denominators\n”;
return 0;
}
cout<<”the lowest common denominator is ”<<endl<<d;
return 0;
}
[2_3]测试下面的注释是否有效?
此注释有效, 单行注释中能够嵌套/*……….*/方式的注释。
[2_4]以下简单的C++程序不可能编译经过, 为什么?
原因是: 在程序中, 当一个函数的定义在后, 而对它的调用在前时, 必须将该函数的原型写在调用语句之前, 而在本程序中缺少函数原型语句。在语句: #include <iostream.h>后加上语句sum(int a,int b);就能够经过了。
[2_5]( 1) 答: 这两个函数原形是等价的, 因为函数原型中的参数名能够缺省。
( 2) 答: 这两个函数的第一行是不等价的, 函数的第一行中必须包含参数名。
( 3) 答: 这两个函数原型是等价的, 因为在函数原型中未注明参数, C++认为该函数的参数表为空( void)
[2_6]答: 输出结果为: 10 20 因为f函数的参数是引用, 因此修改k的值有效。
函数调用后, 主函数中k的值变为10。由于m是对函数的引用, 当m被赋
值为20时, k的值也变为20。
[2_7] 举例说明能够使用const替代#define以消除#define的不安全性
答: 例如: #include <iostream.h>
#define A 2+4
#define B A*3
void main()
{ cout<<B<<endl; }
上面程序的运行结果是14而不是18, 但很容易被认为是18。用const替代#define就能得到正确结果, 从而消除了#define的不安全性。
#include <iostream.h>
const A=2+4;
const B=A*3;
void main()
{ cout<<B<<endl; }
运行结果为18。
[2_8]答: 使用内联函数的优点主要有两个: 一是能加快代码的执行, 减少调用
开销; 二是能消除宏定义的不安全性。
[2_9] 用动态分配空间的方法计算Fibonacci数列的前20项并存储到动态分配的
空间中。
答: #include <iostream.h>
#include ”stdio.h”
void main()
{ int I,*p=new int[20];//动态分配20个整型空间
*p=1;
*(p+1)=1;//前面两个空间赋值1
cout<<*p<<”\t”<<*(p+1)<<”\t”;
p=p+2;//p指向第三个空间
for(i=3;i<=20;i++)
{ *p=*(p-1)+*(p-2);
cout<<*p<<”\t”;
if(i%5==0) cout<<endl;
p++;//指向下一个空间
}
}
结果: 1 1 2 3 5
8 13 21 34 55
89 144 233 377 610
987 1597 2584 4181 6765
[2_10] 建立一个被称为sroot()的函数, 返回其参数的二次方根。重载sroot()三次,
让它返回整数、 长整数与双精度数的二次方根( 计算二次方根时, 能够使用标准
库函数sqrt())
#include <iostream.h>
#include <math.h>
int sroot(int );long sroot(long);double sroot(double);
double sqrt();//声明开方函数sqrt()
void main()
{ int i,x;long l,y;double d,z;
cin>>i; cin>>l; cin>>d;
x=sroot(i); y=sroot(l); z=sroot(d);
cout<<x<<"\t"<<y<<"\t"<<z<<endl;
}
int sroot(int i)
{ return sqrt(i); } //i是整数
long sroot(long l)
{ return sqrt(l); } //l是长整型
double sroot(double d)
{ return sqrt(d); } //d是双精度
//敲进9 16 25
//输出3 4 5
习题[2_11] 编写C++风格的程序, 解决百钱问题, 将一元人民币兑换成1、 2、 5分的硬币, 有多少种换法?
#include <iostream.h>
void main()
{ int i,j,sum=0;
for(i=0;i<=20;i++)
for(j=0;j<=50;j++)
if(100-5*i-2*j>=0)
{
sum++;
cout<<100-5*i-2*j<<”\t”<<j<<”\t”<<i<<endl;
}
cout<<”sum is ”<<sum<<endl;
}
习题[2_12] 编写C++风格的程序, 用二分法求解f(x)=0的根
#include <iostream.h>
#include <math.h>
inline float f(float x)
{ return 2*x*x*x-4*x*x+3*x-6; }
void main()
{ float left,right,middle,ym,yl,yr;
cout<<”pleass two number:”<<endl;//接受输入, 确定第一组数据区域
cin>>left>>right;
yl=f(left);
yr=f(right);
do
{ middle=(right+left)/2;
ym=f(middle);
if(yr*ym>0)
{ right=middle;
Yr=ym;
}
else
{ left=middle;
yl=ym;
}
}while(fabs(ym)>=1e-6);
cout<<”\nRoot is:”<<middle<<endl;
}
本例使用了内联函数f(x),因为在主函数中多次调用它, 这样能够加快代码执行的速度。敲进两个数: -10 10 结果: Root is 2
[2_13]答: 运行结果是: 2 4 6 12 10 说明: 本例使用的是返回引用的值, index(3)=12;语句的执行实际将a[3]赋值为12。
[2_14]答: 运行结果为: 101 说明: 在语句::i=i+1;中赋值号左边::i的i单元是全
局变量, 赋值号右边的i单元是局部变量i。因此执行该语句的结果是
将局部变量i的值+1( 101) 赋值给全局变量i
[2_15]答: 结果是: 10 10 说明: 函数f(&a,b)中的第一个参数是引用, 引用参数是一种按地址传递参数的方法, 对其的调用是传地址调用; 而第二个参数是变量参数, 对它的调用是一般的传值调用。因此运行后, a的值被改为10, b的值不变, 仍为10
[2_16]答: D
说明: int *p=new int(10);表示分配1个整型空间, 初值为10
int *p=new int[10];表示分配10个整型空间
int *p=new int;表示分配1个整型空间
int *p=new int[10](0)想给一个数组分配内存空间时, 对整个数组进行初始化, 这是不允许的。
[2_17]答: D 说明: name被定义为指向常量的常指针, 因此它所指的内容和本
身的内容都不能修改, 而name[3]=’a’;修改了name所指的
常量, name=’lin’;和name=new char[5];修改了常指针, 只有
D输出一个字符是正确的。
[2_18]答: A 说明: name被定义指向常量的指针, 这是一个不能移动的固定指针, 它所指的内容不能改变, 但指针所指的数据能够改变, 而name[3]=’q’;修改了name所指的内容, 是正确的。name=”lin”; name=new char[5]; name=new char(‘q’);以不同的方法修改了常指针, 都是错误的。
[2_19]答: A 说明: name被定义指向常量的指针, 不允许改变指针所指的常量, 但指针本身的内容能够修改, 而name[3]=’q’;修改了name所指的内容, 是错误的。name==”lin” name=new char[5];和name=new char(‘q’)以不同的方法修改了常指针, 都是正确的。
[2_20]答: D 说明: C++中不能建立引用数组和指向引用的指针, 也不能建立引用的引用。因此A、 B、 C是错误的, D是正确的。
第三章: 类和对象( 一)
[3_1]答: 类声明的一般格式如下:
class 类名
{ public:
公有数据成员;
公有成员函数;
protected:
保护数据成员;
保护成员函数;
private:
私有数据成员;
私有成员函数;
}; 其中: class是声明类的关键字; 类名是要声明的类的名字; 后面的花括号表示出类声明的范围; 最后的分号表示类声明结束。
[3_2]答: 构造函数是一种特殊的成员函数, 它主要用于为对象分配空间, 进行初始化。构造函数具有一些特殊的性质:
( 1) 构造函数的名字必须与类名相同
( 2) 构造函数能够有任意类型的参数, 但不能指定返回类型。它有隐含的返回值, 该值在系统内部使用。
( 3) 构造函数是特殊的成员函数, 函数体可写在类体内, 也可写在类体外。
( 4) 构造函数能够重载, 即一个类中能够定义多个参数个数或参数类型不同的构造函数。
( 5) 构造函数被声明为公有函数, 但它不能象其它成员函数那样被显示地调用, 它是在定义对象的同时被调用的。
析构函数也是一种特殊的成员函数。它执行与构造函数相反的操作, 一般见
于撤消对象时的一些清理任务, 如释放分配给对象的内存空间等。析构函数有以下一些特点:
( 1) 析构函数与构造函数名字相同, 但它前面必须加一个波浪号( ~)
( 2) 析构函数没有参数, 不能指定返回类型, 而且不能重载。因此在一个类中只能有一个析构函数。
( 3) 当撤消对象时, 编译系统会自动地调用析构函数。
[3_3]答: B 说明: C++中对构造函数有一些规定: 不能带返回值; 能够不带
参数; 也能够缺省定义; 但构造函数的名字与类名必须完全相同。
[3_4]答: C 说明: C++中没有限定private、 public、 protected的书写次序。但
是, 不能在类的声明中给数据成员赋初值, 数据成员的数据类型
也不能是register( 寄存器类型) , 没有用private、 public、 protected
定义的数据成员是私有成员。
[3_5]答: C 说明: C++中对析构函数也有一些规定: 没有参数; 不能重载; 析构函数的名字是在类名前加”~”; 析构函数不能指定返回类型。
[3_6]答: B 说明: 构造函数的工作是在创立对象时执行的。
[3_7]答: 语句”p1.age=30;”出现错误。因为age是私有数据成员, 不能直接访问。
[3_8]答: 第1个错误: printStu、 setSno两个成员函数没有用public定义, 则不
允许外部函数对对象进行操作。
第2个错误: 成员函数在类外定义, 应加上类名”Student::”。
第3个错误: setAge应在类中说明, 而且在类外定义时, 应加上类名”Student::”。
[3_9]答: 语句”Point cpoint;”是错误的, 它试图用私有的构造函数Point访问公有数据成员x和y, 这是不正确。
[3_10]答: 语句Stack stt;”应该带参数, 因为当类中没有定义构造函数时, 编译器会自动生成一个缺省的不带参数的构造函数。可是, 如果类中有自己定义的构造函数后, 编译器将不再自动生成一个缺省的构造函数。例如: 将上述语句改成”Stack stt(10);”就正确了。
[3_11]:下面是一个计数器的定义, 请完成该类成员函数的实现
#include <iostream.h>
class counter
{ public:
counter(int number);//构造函数
void increment(); //给原值加1
void decrement(); ///给原值减1
int getvalue(); //取得计数器值
int print(); //显示计数
private:
int value;
};
counter::counter(int number)//构造函数定义
{ value=number; }
void counter::increment()//给原值加1
{ value++; }
void counter::decrement()//给原值减1
{ value--; }
int counter::getvalue()//取得计数器值
{ return value; }
int counter::print()//显示计数
{ cout<<"value is "<<value<<endl;
return 0;
}
main()
{ int i;
cin>>i;
counter a(0);
for(int j=0;j<i;j++)
{ a.increment();
a.getvalue();
a.print();
}
counter b(10);
for(int k=1;k<i;k++)
{ b.decrement();
b.getvalue();
b.print();
}
return 0;
}
习题: [3_12]根据注释语句的提示, 实现类Date的成员函数
#include <iostream.h>
class Date
{ public:
void printDate(); //显示日期
void setDay(int d);//设置日期值
void setMonth(int m);//设置月的值
void setYear(int y);//设置年的值
private:
int day,month,year;
};
void main()
{ Date testDay;
testDay.setDay(5);
testDay.setMonth(10);
testDay.setYear( );
testDay.printDate();
}
void Date::printDate()
{ cout<<"\nDate is "<<year<<".";
cout<<month<<"."<<day<<endl;
}
void Date::setDay(int d)
{ day=d; }
void Date::setMonth(int m)
{ month=m; }
void Date::setYear(int y)
{ year=y; }
习题: [3_13]下面定义了一个类date,根据主程序的提示, 实现重载构造函数date()
#include <iostream.h>
#include <stdio.h>
class date
{ public:
date(int d,int m,int y);
date::date();
void show();
private:
int day,month,year;
};
void date::show()
{ cout<<day<<'/'<<month<<'/';
cout<<year<<"\n";
}
main()
{ date idate(28,10,1949);//构造函数的参数为3个整数
idate.show();
date indate; //构造函数没有参数, 数据经过键盘直接输入
indate.show();
return 0;
}
//解: 重载构造函数的实现如下:
date::date(int d,int m,int y)
{ day=d;
month=m;
year=y;
}
date::date()
{ cout<<"Enter month_day_year:\n";
cin>>day;
cin>>month;
cin>>year;
}//注意: 敲数据时要如: 8 回车 9回车 回车
习题: [3_14]建立类cylinder, cylinder的构造函数被传递了两个double值, 分别表示圆柱体的半径和高度。用类cylinder计算圆柱体的体积, 并存储在一个double变量中。在类cylinder中包含一个成员函数vol(), 用来显示每个cylinder对象的体积。
#include <iostream.h>
class cylinder
{ public:
cylinder(double a,double b);
void vol();
private:
double r,h;
double volume;
};
cylinder::cylinder(double a,double b)
{ r=a; h=b;
volume=3.141592*r*r*h;
}
void cylinder::vol()
{ cout<<"volume is: "<<volume<<"\n"; }
void main()
{
cylinder x(2.2,8.09);
x.vol();
}
习题: [3_15]建立一个Stock类, 含有股票代码和股票现价两个数据成员。用new自动为Stock类的对象分配内存, 并将股票代码”600001”, 现价8.89存入内存的相应域中。
#include <iostream.h>
#include <string.h>
class Stock
{ public:
void set(char *c,float pr);
void print();
private:
char Stockcode[7];
float price;
};
void Stock::set(char *c,float pr)
{ strcpy(Stockcode,c);
price=pr;
}
void Stock::print()
{ cout<<Stockcode<<": "<<price;
cout<<"\n";
}
main()
{ Stock *p;
p=new Stock; //为对象分配空间
if(!p) //判断分配是否成功
{ cout<<"Allocation error.";
return 1;
}
p->set("600001",8.89);//为对象赋值
p->print(); //显示对象
delete p;
return 0;
}
习题: [3_16]声明一个栈类, 利用栈操作实现将输入字符串反向输出的功能
#include <iostream.h>
//#include <iomanip.h>
//#include <ctype.h>
#include <string.h>
const int SIZE=10;
class stack
{ public:
stack() //构造函数
{ tos=0; }
void push(char ch);//将数据ch压入栈
char pop(); //将栈顶数据弹出栈
char stck[SIZE]; //数组, 用于存放栈中数据SIZE上面赋值为10
int tos; //栈顶位置( 数组下标)
};
//stack::stack() //构造函数, 初始化栈
//{ tos=0; }
void stack::push(char ch)//压入栈
{
if(tos==SIZE)
{
cout<<"Stack is full";//栈是满的
return;
}
stck[tos]=ch;
tos++;
}
char stack::pop()//弹出栈
{
if(tos==0)
{ cout<<"Stack is empty";//栈是空的
return 0;
}
tos--;
return stck[tos];
}
void main()
{ int i;
char str[20];
char re_str[20];
cout<<"\nplease input a string: ";
cin>>str;
stack ss;
for(i=0;i<strlen(str);i++)
ss.push(str[i]);
for(i=0;i<strlen(str);i++)
re_str[i]=ss.pop();
re_str[i]='\0';
cout<<"\nreverse string: ";
cout<<re_str<<endl;
}
附: 用C写反序输出程序
步骤: 打开VC系统, FileànewàFileàC++Source Fileà改变路径Location为本章的路径àFile处写文件名àokà开始写C程序à之后编译运行
#include <stdio.h>
#include <string.h>
//#include <ctype.h>
main()
{ int inverse(char str[]); //函数原型说明
char str[100];
printf("Input string: ");
scanf("%s",str);
inverse(str);
printf("Inverse string: %s\n",str);
}
int inverse(char str[]) //函数定义
{ char t;
int i,j;
for(i=0,j=strlen(str);i<strlen(str)/2;i++,j--)
{ t=str[i];
str[i]=str[j-1];
str[j-1]=t;
}
return 0;
}第四章: 类和对象( 二)
[4_1]什么是对象数组
所谓对象数组是指每一数组元素都是对象的数组, 也就是说, 若一个类有若干个对象, 我们把这一系列的对象用一个数组来存放。对象数组的元素是对象, 不但具有数据成员, 而且还有函数成员。
[4_2]什么是this指针? 它的主要作用是什么?
C++为成员函数提供了一个名字为this的指针, 这个指针称为自引用指针。每当创立一个对象时, 系统就把this指针初始化为指向该对象。每当调用一个成员函数时, 系统就自动把this指针作为一个隐含的参数传给该函数。不同的对象调用同一个成员函数时, C++编译器将根据成员函数的this指针所指向的对象来确定应该引用哪一个对象的数据成员。
[4_3]友元函数有什么作用?
友元函数不是当前类的成员函数, 而是独立于当前类的外部函数, 但它能够访问该类的所有对象的成员, 包括私有成员和公有成员。经过友元函数能够在不放弃私有数据安全的情况下, 使得类外部的函数能够访问类中的私有成员。
当一个函数需要访问多个类时, 友元函数非常有用, 普通的成员函数只能访问其所属的
展开阅读全文