• 337.00 KB
  • 2022-04-22 11:29:51 发布

面向对象程序设计C++课后题答案.doc

  • 92页
  • 当前文档由用户上传发布,收益归属用户
  1. 1、本文档共5页,可阅读全部内容。
  2. 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,可选择认领,认领后既往收益都归您。
  3. 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细先通过免费阅读内容等途径辨别内容交易风险。如存在严重挂羊头卖狗肉之情形,可联系本站下载客服投诉处理。
  4. 文档侵权举报电话:19940600175。
'第一章:面向对象程序设计概述[1_1]什么是面向对象程序设计?面向对象程序设计是一种新型的程序设计范型。这种范型的主要特征是:程序=对象+消息。面向对象程序的基本元素是对象,面向对象程序的主要结构特点是:第一:程序一般由类的定义和类的使用两部分组成,在主程序中定义各对象并规定它们之间传递消息的规律。第二:程序中的一切操作都是通过向对象发送消息来实现的,对象接受到消息后,启动有关方法完成相应的操作。面向对象程序设计方法模拟人类习惯的解题方法,代表了计算机程序设计新颖的思维方式。这种方法的提出是软件开发方法的一场革命,是目前解决软件开发面临困难的最有希望、最有前途的方法之一。[1_2]什么是类?什么是对象?对象与类的关系是什么?在面向对象程序设计中,对象是描述其属性的数据以及对这些数据施加的一组操作封装在一起构成的统一体。对象可以认为是:数据+操作在面向对象程序设计中,类就是具有相同的数据和相同的操作的一组对象的集合,也就是说,类是对具有相同数据结构和相同操作的一类对象的描述。类和对象之间的关系是抽象和具体的关系。类是多个对象进行综合抽象的结果,一个对象是类的一个实例。在面向对象程序设计中,总是先声明类,再由类生成对象。类是建立对象的“摸板”,按照这个摸板所建立的一个个具体的对象,就是类的实际例子,通常称为实例。[1_3]现实世界中的对象有哪些特征?请举例说明。对象是现实世界中的一个实体,其具有以下一些特征:(1)每一个对象必须有一个名字以区别于其他对象。92 (2)需要用属性来描述它的某些特性。(3)有一组操作,每一个操作决定了对象的一种行为。(4)对象的操作可以分为两类:一类是自身所承受的操作,一类是施加于其他对象的操作。例如:雇员刘名是一个对象    对象名:刘名对象的属性:年龄:36 生日:1966.10.1 工资:2000 部门:人事部    对象的操作:吃饭  开车[1_4]什么是消息?消息具有什么性质?在面向对象程序设计中,一个对象向另一个对象发出的请求被称为“消息”。当对象接收到发向它的消息时,就调用有关的方法,执行相应的操作。消息是一个对象要求另一个对象执行某个操作的规格的说明,通过消息传递才能完成对象之间的相互请求或相互协作。消息具有以下3个性质:(1)同一个对象可以接收不同形式的多个消息,做出不同的响应。(2)相同形式的消息可以传递给不同的对象,所做出的响应可以是不同的。(3)消息的发送可以不考虑具体的接收者,对象可以响应消息,也可以不响应。[1_5]什么是方法?消息和方法的关系是什么?在面向对象程序设计中,要求某一对象作某一操作时,就向该对象发送一个响应的消息,当对象接收到发向它的消息时,就调用有关的方法,执行响应的操作。方法就是对象所能执行的操作。方法包括界面和方法体两部分。方法的界面也就是消息的模式,它给出了方法的调用协议;方法体则是实现某种操作的一系列计算步骤,也就是一段程序。在C++语言中方法是通过函数来实现的,称为成员函数。消息和方法的关系是:对象根据接收到的消息,调用相应的方法;反过来,有了方法,对象才能响应相应的消息。[1_6]什么是封装和抽象?请举例说明。92 在现实世界中,所谓封装就是把某个事物包围起来,使外界不知道该事物的具体内容。在面向对象程序设计中,封装是指把数据和实现操作的代码集中起来放在对象内部,并尽可能隐蔽对象的内部细节。对象好象是一个不透明的黑盒子,表示对象属性的数据和实现各个操作的代码都被封装在黑盒子里,从外面是看不见的,更不能从外面直接访问或修改这些数据及代码。使用一个对象的时候,只需要知道它向外界提供的接口形式而无需知道它的数据结构细节和实现操作的算法。封装机制可以将对象的使用者与设计者分开,使用者不必知道对象行为实现的细节,只需要使用设计者提供的接口让对象去做。抽象是人类认识问题的最基本的手段之一。它忽略了一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象是对复杂世界的简单表示,抽象强调感兴趣的信息,忽略了不重要的信息。例如,设计一个学籍管理程序的过程中,考察某个学生对象时,只关心他的姓名、学好、成绩等,而对他的身高、体重等信息就可以忽略。以一般观点而言,抽象是通过特定的实例(对象)抽象共同性质以后形成概念的过程。抽象是对系统的简化描述或规范说明,它强调了系统中的一部分细节和特性,而忽略了其他部分。抽象包括两个方面:数据抽象和代码抽象(或称为行为抽象)。前者描述某类对象的属性或状况,也就是此类对象区别于彼类对象的特征物理量;后者描述了某类对象的共同行为特征或具有的共同操作。在面向对象程序设计方法中,对一个具体问题的抽象分析的结果,是通过类来描述和实现的。现在以学生管理程序为例,通过对学生进行归纳、分析,抽取出其中的共性,可以得到如下的抽象描述:共同的属性:姓名、学号、成绩等,他们组成了学生数据抽象部分。用C++语言的数据成员来表示,可以是:  char*name;intnumber;floatscore;92 共同的行为:数据录入、数据修改和数据输出等,这构成了学生的行为抽象部分,用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]什么是多态性?举例说明。92    多态性也是面向对象程序设计的重要特性。它是指不同的对象收到相同的消息时产生不同的行为方式。例如我们同样双击windows系统桌面上的图标时,有的是打开多媒体播放器,有的是打开资源管理器。利用多态性,用户只需发送一般形式的消息,而将所有的实现留给接收消息的对象。对象根据所收到的消息做出相应的动作。[1_11]什么是函数重载和运算符重载?为什么要使用重载?   重载一般包括函数重载和运算符重载。函数重载是指一个表示符可同时用于为多个函数命名,而运算符重载是指一个运算符可同时用于多种运算。也就是说,相同名字的函数或运算符在不同的场合可以表现出不同的行为。       使用重载的目的是为了更好地表达行为共享,这种行为共享就象将相似的操作划分在一起。使用重载可以使程序员在只知道操作的一般含义,而不知道操作的具体细节的情况下能正确地对某个对象使用一个操作。另外,使用重载的直接益处是减少了程序员记忆操作的名字的负担。92 第二章::C++基础[2_1]简述C++的主要特点(1)C++保持与C的兼容,用C编写的软件可以用到C++中。(2)用C++编写的程序可读性好,代码结构更合理,可直接地在程序中映射问题空间的结构。(3)生成代码的质量高。(4)软件的可重用性、可扩充性、可维护性和可靠性有了明显的提高,从而节省了开发费用和时间。(5)支持面向对象的机制,可方便地构造出模拟现实问题的实体和操作。[2_2]下面是一个C程序,改写它,使它采用C++风格的i/o语句改写如下:#includemain(){ inta,b,d,min;cout<<”entertwonumbers:“;cin>>a;cin>>b;min=a>b?b:a;for(d=2;d后加上语句sum(inta,intb);就可以通过了。[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             #defineA2+4             #defineBA*3             voidmain()             { cout<92 constA=2+4;constB=A*3;voidmain(){ cout<  #include“stdio.h”voidmain(){ intI,*p=newint[20];//动态分配20个整型空间  *p=1;*(p+1)=1;//前面两个空间赋值1cout<<*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<#includeintsroot(int);longsroot(long);doublesroot(double);doublesqrt();//声明开方函数sqrt()voidmain(){inti,x;longl,y;doubled,z; cin>>i; cin>>l; cin>>d; x=sroot(i);y=sroot(l);z=sroot(d); cout<voidmain(){ inti,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”<#includeinlinefloatf(floatx){ return2*x*x*x-4*x*x+3*x-6; }voidmain(){ floatleft,right,middle,ym,yl,yr;  cout<<”pleasstwonumber:”<>left>>right;  yl=f(left);  yr=f(right);92 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<<”nRootis:”<classcounter{ public:    counter(intnumber);//构造函数    voidincrement(); //给原值加1    voiddecrement(); ///给原值减1    intgetvalue();    //取得计数器值    intprint();       //显示计数  private:    intvalue;};counter::counter(intnumber)//构造函数定义{ value=number; }voidcounter::increment()//给原值加1{ value++; }voidcounter::decrement()//给原值减1{ value--; }   intcounter::getvalue()//取得计数器值{ returnvalue; }intcounter::print()//显示计数{ cout<<"valueis"<>i;  countera(0);  for(intj=0;jclassDate{ public:    voidprintDate(); //显示日期       voidsetDay(intd);//设置日期值       voidsetMonth(intm);//设置月的值92        voidsetYear(inty);//设置年的值private:      intday,month,year;};voidmain(){ DatetestDay;  testDay.setDay(5);  testDay.setMonth(10);  testDay.setYear(2003);  testDay.printDate();}voidDate::printDate(){ cout<<"nDateis"<#includeclassdate92 { public:     date(intd,intm,inty);       date::date();       voidshow();private:      intday,month,year;};voiddate::show(){ cout<>day;  cin>>month;  cin>>year;}//注意:敲数据时要如:8回车9回车2005回车习题:[3_14]建立类cylinder,cylinder的构造函数被传递了两个double值,分别表示圆柱体的半径和高度。用类cylinder计算圆柱体的体积,并存储在一个double变量中。在类cylinder中包含一个成员函数vol(),用来显示每个cylinder对象的体积。#includeclasscylinder{ public:    cylinder(doublea,doubleb);       voidvol();private:      doubler,h;      doublevolume;};cylinder::cylinder(doublea,doubleb){ r=a;h=b;  volume=3.141592*r*r*h;}voidcylinder::vol(){ cout<<"volumeis:"<#includeclassStock{public:   voidset(char*c,floatpr);      voidprint();private:      charStockcode[7];      floatprice;};voidStock::set(char*c,floatpr){ strcpy(Stockcode,c);  price=pr;}voidStock::print(){ cout<set("600001",8.89);//为对象赋值  p->print();          //显示对象  deletep;  return0;}习题:[3_16]声明一个栈类,利用栈操作实现将输入字符串反向输出的功能#include//#include//#include#includeconstintSIZE=10;classstack{ public:    stack()          //构造函数       {tos=0;}       voidpush(charch);//将数据ch压入栈       charpop();       //将栈顶数据弹出栈       charstck[SIZE];  //数组,用于存放栈中数据SIZE上面赋值为1092        inttos;          //栈顶位置(数组下标)};//stack::stack()    //构造函数,初始化栈//{ tos=0; }voidstack::push(charch)//压入栈{      if(tos==SIZE)      {             cout<<"Stackisfull";//栈是满的             return;      }      stck[tos]=ch;      tos++;}charstack::pop()//弹出栈{      if(tos==0)      {cout<<"Stackisempty";//栈是空的       return0;      }      tos--;      returnstck[tos];}voidmain(){ inti;92   charstr[20];  charre_str[20];  cout<<"npleaseinputastring:";  cin>>str;  stackss;  for(i=0;i#include//#includemain(){intinverse(charstr[]); //函数原型说明 charstr[100]; printf("Inputstring:"); scanf("%s",str); inverse(str);92  printf("Inversestring:%sn",str);}intinverse(charstr[])  //函数定义{ chart;  inti,j;  for(i=0,j=strlen(str);iget_sno()<<”n”;因为:非静态成员函数的调用方法与静态成员函数的调用方法不同。[4_9]答:#include#includeclassCTest{ public:    constinty2;    CTest(inti1,inti2):y1(i1),y2(i2)92     { y1=10; //错误,y1是调用const定义的,不能修改       x=y1;     }    intreadme()const;     //…..  private:    intx;constinty1;};intCTest::readme()const{ inti;  i=x;  x++; //错误,函数定义用了const,表示该函数不能修改对象  returnx;}voidmain(){ CTestc(2,8);  inti=c.y2;  c.y2=i; //错误,y2是常量,不能修改  i=c.y1; //错误,y1是私有变量,不能直接存取}[4_10]答:#include#includeclassCTest92 { public:     CTest()    {x=20;}    voiduse_friend();  private:    intx;    friendvoidfriend_f(CTestfri); };voidfriend_f(CTestfri){ fri.x=55; }voidCTest::use_friend(){ CTestfri;  this->friend_f(fri); //错误。友元函数不是成员函数,所以不能用this->调用友//元函数  ::friend_f(fri);}voidmain(){ CTestfri,fri1;  fri.friend_f(fri); //错误,友元函数不是成员函数,所以不能用对象.函数名调//用友元函数friend_f(fri1);}[4_11]答:#include#include92 classCTest{ public:    CTest()     { x=20; }    voiduse_this();  private:    intx;};voidCTest::use_this(){ CTesty,*pointer;  this=&y; //错误,不能对this直接赋值  *this.x=10;//错误,按优先级原句的含义是*(this.x)=10,显然不对,正确的写//法是(*this).x=10;或this->x=10;pointer=this;pointer=&y;}voidmain(){ CTesty;  this->x=235; //错误,this的引用不能在外部函数中,只能在内部函数中。}[4_12]答:运行结果是:10,2030,4850,6870,8092 90,1611,120[4_13]答:运行结果是:Constructing10Destructing.100Destructing[4_14]答:运行结果是:3objectsinexistence4objectsinexistenceafterallocation3objectsinexistenceafterdeletion说明:这个程序使用静态数据成员追踪记载创建对象的个数。完成这一工作的方法就是每创建一个对象就调用构造函数一次。每调用构造函数一次,静态数据成员total就增加1,每撤消一个对象就调用析构函数一次。每调用析构函数一次,静态数据成员total就减少1。[4_15]运行结果是:Here’stheprogramoutput.Let’sgeneratesomestuff…Countingat0Countingat1Countingat2Countingat3Countingat4Countingat592 Countingat6Countingat7Countingat8Countingat9说明:在程序中main()只包括了一个return语句,但竟然有内容输出!什么时候调用了构造函数?构造函数在对象被定义时调用。那么对象anObject是何时被调用的呢?是在main()之前,语句”testanObject”处。因此,anObject的构造函数是先于main()被调用的。在main()之前的所有全局变量都是在main()开始之前就建立了的。应该尽可能避免使用全局变量,因为全局变量有可能引起名称冲突,使程序的执行结果和预想的不一样。          [4_16][4_17]构建一个类book,其中含有2个私有数据成员qu和price,建立一个有5个元素的数组对象,将qu初始化为1~5,将price初始化为qu的10倍。显示每个对象的qu*price 答案见下:#includeclassbook{ public:    book(inta,intb)       {qu=a; price=b; }       voidshow_money()       {cout<show_money();  p--;}return0;}[4_18]使用C++的 见书139页题#include//#includeclasstoy{ public:  toy(){}  toy(intp,intc)  { price=p;     count=c;92   }  voidinput(intp,intc);  voidcompute();  voidprint();private:      intprice;      intcount;      longtotal;};voidtoy::input(intp,intc){ price=p;  count=c;}voidtoy::compute(){ total=(long)price*count; }voidtoy::print(){cout<<"price="<#include#includeconstintSIZE=80;classstock{ public:    stock()       { strcpy(stockcode,""); }       stock(charcode[],intq=1000,floatp=8.98)       {strcpy(stockcode,code);        quan=q;        price=p;       }       voidprint(void)92        { cout<stockcode;         cout<<""<quan<<""<price<#include#includeclassshen_stock;  //深圳类classshang_stock  //上海类{public:   shang_stock(intg,ints,intp); //构造函数      friendvoidshang_count(constshang_stockss);//计算上海的                                                   //股票总数      friendvoidcount(constshang_stockss,constshen_stockzs);                           //计算上海和深圳的股票总数private:      intgeneral;//普通股票个数      intst;     //ST股票个数      intpt;     //PT股票个数};shang_stock::shang_stock(intg,ints,intp)//构造函数{ general=g;  st=s;  pt=p;}classshen_stock{ intgeneral; //普通股票个数92   intst;      //ST股票个数  intpt;      //PT股票个数public:      shen_stock(intg,ints,intp);//构造函数      friendvoidshen_count(constshen_stockes);//计算深圳的股票总数      friendvoidcount(constshang_stockss,constshen_stockzs);                            //计算上海和深圳的股票总数};shen_stock::shen_stock(intg,ints,intp)//构造函数{ general=g;  st=s;  pt=p;}main(){ shang_stockshanghai(1600,20,10);//建立对象     //表示上海有1600支股票,20支ST股票,10支PT股票  shen_stockshenzhen(1500,15,8); //建立对象     //表示深圳有1500支股票,15支ST股票,8支PT股票  shang_count(shanghai);//计算上海的股票总数  shen_count(shenzhen);//计算深圳的股票总数  count(shanghai,shenzhen);//计算上海和深圳的股票总数  return0;}voidshang_count(constshang_stockss)//计算上海的股票总数{ints;92  cout<<"stocksofshanghaiare"<#includeclasstable{ protected:    inti,j;public:      table(intp,intq)      { i=p; j=q; }      voidascii(void);};voidtable::ascii(void){ intk=1;  for(;i#includeclasstime{ public:    time(inth,intm,ints)       { hours=h;         minutes=m;             seconds=s;       }92        virtualvoiddisplay()       { cout<#includeclassanimal{ public:    animal()       { name=NULL; }       animal(char*n);       ~animal()       { deletename; }       virtualvoidwhoami();protected:      char*name;};classcat:publicanimal92 { public:    cat():animal()       {     }       cat(char*n):animal(n)       {     }       voidwhoami();};classtiger:publiccat{ public:    tiger():cat()       {    }       tiger(char*n):cat(n)       {    }       voidwhoami();};animal::animal(char*n){ name=newchar[strlen(n)+1];  strcpy(name,n);}voidanimal::whoami(){ cout<<"genericanimal"; }voidcat::whoami(){ cout<<"iamacatname"<classbuilding{ public:  building(intf,intr,doubleft)  { floors=f;     rooms=r;       footage=ft;  }protected:      intfloors;//层数      introoms; //房间数      doublefootage;//平方数};classhouse:publicbuilding{ public:  house(intf,intr,doubleft,intbr,intbth)nbsp;  :building(f,r,ft)  {  bedrooms=br; bathrooms=bth; }92   voidshow()  { cout<<"floors:"<#includeconstintl=80;classperson{ public:    voidinput()       { cout<<"ninputname:";         cin>>name;             cout<<"ncertificateno:";             cin>>id;       }       voidprint()       { cout<<"ncertificateno:"<>addr;        cout<<"inputtelphoneno:";        cin>>tel;      }      voidprint()      {    cout<<"naddress:"<<"t"<>old;             cout<<"inputscoreno:";             cin>>sno;       }       voidprint()       { person::print();          cout<<"ntearsold:"<<"t"<>math;             cout<<"inputenglishscore:";             cin>>eng;       }       voidprint()       { student::print();         stud::print();             cout<<"nmathscore:"<<"t"<>degree;             cout<<"inputdepartment:";             cin>>dep;       }       voidprint()       { person::print();         cout<<"ndegree:"<<"t"<print()均执行Stock::print(),而不执行Der1_Stock::print()或Der2_Stock::print(),这是因为基类和派生类定义的print()函数的返回值类型、参数类型和个数均相同,基类中定义的print()未声明成虚类型(virtual),这时的函数调用是在编译时静态联编的。[6_11]题:将上例基类Stock中的print()函数前面加virtual就行了。[6_12]题:程序实现如下:#includeclasscar{ public:    doubledistance;       car(doublef)       { distance=f; }       virtualvoidtravel_time()92        { cout<<"car:traveltimeat120kph:";         cout<travel_time();  p=&truck_time;  p->travel_time();  return0;}[6_13]题:程序如下:#includeclasscurrency{ public:    voidset_j(floatj)       { japan=j; }92        voidset_e(floate)       { europe=e; }       virtualvoidprint_exchange()=0;protected:      floatjapan,europe;};classja:publiccurrency{ public:    voidprint_exchange()       { cout<<"10000jaexchange$:"<<10000/japan;         cout<set_j(116.30);  ptr[0]->print_exchange();  ptr[1]=&e1;92   ptr[1]->set_e(1.1634);  ptr[1]->print_exchange();  return0;}[6_14]题:程序如下:#includeclasscurrency{ public:    voidset_j(floatj)       { japan=j; }       voidset_e(floate)       { europe=e; }       virtualvoidprint_exchange(floata)=0;//加浮点参数a   protected:       floatjapan,europe;};classja:publiccurrency{ public:    voidprint_exchange(floata) //加浮点参数a       { cout<<"10000jaexchange$:"<set_j(116.30);  ptr[0]->print_exchange(100000);//放任意数  ptr[1]=&e1;  ptr[1]->set_e(1.1634);  ptr[1]->print_exchange(1000);//放任意数  return0;}92 第七章:运算符重载习题:[7_1]简述运算符重载的规则(1)运算符重载是针对新类型数据的实际需要,对原有运算符进行适当的改造完成的。一般来讲,重载的功能应当与原有的功能相类似。(2)C++语言中只能重载原先已有定义的运算符。(3)不是所有的运算符都能重载,它们是:类属关系运算符“.”、成员指针运算符“*”、作用域分辨符“::”、sizeof运算符和三目运算符“?:”如(x>y)?x:y(4)运算符重载不能改变运算符的操作个数(5)运算符重载不能改变运算符原有的优先级(6)运算符重载不能改变运算符原有的结合性(7)运算符重载不能改变运算符对预定义类型数据的操作方式[7_2]友元运算符函数和成员运算符函数有什么不同?(1)运算符函数可以定义为它将要操作的类的成员,称为成员运算符函数;定义为类的友元函数,称为友元运算符函数。对双目而言,成员运算符函数带有一个参数,而友元运算符函数带有2个参数;对单目运算符而言,成员运算符函数不带参数,而友元运算符函数带一个参数。(2)双目运算符一般可以被重载为友元运算符函数或成员运算符函数,但当双目运算符的左操作数是一个基本数据类型,而右操作数是一个类类型时必须使用友元运算符函数。(3)成员运算符函数和友元运算符函数可以用习惯方式调用,也可以用它们专用的方式调用[7_3]答:D说明:C++语言允许在重载运算符时改变运算符的原来的功能。例如将++符号重载时,可以定义为--的功能。但是,不提倡这样做。重载的功能应当与原有的功能类似。[7_4]答:A 说明:C++规定不能用友元函数重载“=”、“[]”和“->”92 [7_5]答:运行结果为:7 6 说明:重载++运算符时使用的友元函数无法引用this指针,函数通过传值的方法传递参数,函数体内对数据成员的改动无法传到函数体外。所以,(++I)以后,I.xi无任何改动。[7_6]答:结果为5 7 说明:本题是重载运算符(),用()模拟数组运算符[]。[7_7]答:++dl的调用是非法的,因为重载的是后缀“++”[7_8]编一程序,用成员函数重载运算符“+”和“-”将2个二维数组相加和相减,要求第一个二维数组的值由构造函数设置,另一个二维数组的值由键盘输入。#include#includeconstintrow=2;  constintcol=3;classarray{ public:     array()       { inti,j,k=1;       for(i=0;i>var[i][j];       }       voiddisplay()//显示数组的值92        { inti,j;          for(i=0;i#includeconstintrow=2;constintcol=3;classarray{ public:     array()       { inti,j,k=1;       for(i=0;i>var[i][j];       }       voiddisplay()//显示数组的值       { inti,j;          for(i=0;iclassDate{ public:    Date()       {    }       Date(intm,intd,inty)       { month=m;92          day=d;             year=y;       }       voidprint()       { cout<year);  n+=this->day;  while(n>days[leap][this->month-1])  { n-=days[leap][this->month-1];     if(++(this->month)==13)       { this-&g;month=1;          (this->year)++;              leap=isleap(this->year);92        }  }  this->day=n;  return*this;}voidmain(){ Dated1(2,15,2000),d2;  d1.print();  d2=d1+95;  d2.print();}92 第八章:模板[8_1]为什么使用摸板?函数摸板声明的一般形式是什么?摸板是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型定义为参数,从而实现了真正的代码重用。使用摸板可以大幅度地提高程序设计的效率。函数摸板的一般说明形式如下:template返回类型函数名(摸板形参表){  函数体}其中,template是一个声明摸板的关键字,它表示声明一个摸板。类型参数前需要加关键字class(或typename).[8_2]什么是摸板实参和摸板函数?  将函数摸板中实例化的参数称为摸板实参,用摸板实参实例化的函数称为摸板函数。[8_3]为什么使用类摸板,类摸板和摸板类之间的关系是什么?   类摸板允许用户为类定义一种模式,使得类中的某些数据成员、某些成员函数的参数或返回值能取任意数据类型。   类摸板不是代表一个具体的、实际的类,而是代表着一类类。摸板类是类摸板对某一特定类型的实例,表示某一具体的类。[8_4]函数模板与同名的非模板函数重载时,调用的顺序是怎样的?(1)寻找一个参数完全匹配的函数,如果找到了就调用它。(2)寻找一个函数模板,将其实例化,产生一个匹配的模板函数,若找到了,就调用它。(3)若(1)和(2)都失败了,再试一试低一级的对函数的重载方法,例如通过类型转换可产生参数匹配等,若找到了,就调用它。92 若(1)(2)(3)均未找到匹配的函数,则是一个错误的调用。如果在第(1)步有多于一个的选择,那么这个调用是意义不明确的,是一个错误调用。[8_5]D  说明:实例化的摸板实参之间必须保持一致的类型[8_6]A      [8_7]运行结果:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,ioutofrange    说明:Holder类的大小是20,所以输出下标为21的元素会输出ioutofrange[8_8]运行结果为:10 0.23    XThisisatest    说明:程序声明了两种类型的对象。ob1的两个参数分别为整形与双精度型,ob2的两个参数分别为字符型与字符串型。[8_9]解:主函数中语句”StackaSt(5);”是错误的,因为首先要将模板实例化,才能由模板生成对象。应该将此语句改为”StackaSt(5);”[8_10]解:#includetemplateTypemin(Typea,Typeb,Typec){ a=(atemplateTypemax(Type*Array,intsize){ inti,j=0;  for(i=1;iArray[j])        { j=i; }        returnArray[j];}voidmain(){ intintArray[]={11,12,13,14,7,8,9};  doubledArray[]={11.2,12.3,13.2,14.5,14.8,8.7,9.3};  cout<templatevoidsort(Type*Array,intsize){ inti,j;  for(i=0;iArray[j+1])               { Typetemp=Array[j];                  Array[j]=Array[j+1];                     Array[j+1]=temp;               }}voidmain(){ intintArray[]={11,12,13,14,7,8,9};  inti;  sort(intArray,7);  cout<templateclassinput{ public:    input(char*s,Xmin,Xmax);private:  Xdata;};templateinput::input(char*s,Xmin,Xmax){      do      {cout<>data;      }      while(datamax);}main(){ inputi("enterint",0,10);  inputc("enterchar","A","Z");  cout<<"---end---"<templateclasslist{ public:    list(data_td);       voidadd(list*node)       { node->next=this;         next=0;       }       list*getnext()       { returnnext; }       data_tgetdata()       { returndata; }private:      data_tdata;      list*next;};92 templatelist::list(data_td){ data=d;  next=0;}main(){ liststart("a");  list*p,*last;  inti;  //建立链表  last=&start;  for(i=1;i<26;i++)  { p=newlist("a"+i);     p->add(last);       last=p;  }  //显示链表  p=&start;  while(p)  { cout<getdata();     p=p->getnext();  }  cout<92 start(‘a’);声明。注意所要求的数据类型是如何通过放在角括号内传递的。该程序建立了包含字母表字符的链表,并显示它们。但是,在建立对象的时候,只通过改变指定的数据类型,就可以改变表所保存的数据类型。例如,可以用声明:listint_start(1);建立保存整数的其它对象。[8_16]程序实现如下:#include#includetemplateclassnode{ public:    Typedata;       node*next;};templateclassStacklink{ public:    Stacklink();//构造函数       ~Stacklink();//析构函数       voidpush(Typevalue);//进栈       Typepop();//出栈,并返回栈顶元素       intisnull();//判栈空private:      node*top;};templateStacklink::Stacklink(){ node*T;  T=newnode;//申请一个空间  T->next=NULL;//指针项清092   top=T;//栈顶指针指向新申请的空间  //本例使用的是带头结点的单链表,第一个结点不会存储栈元素}templateStacklink::~Stacklink()//析构函数,删除单链表中的所有结点{ node*N,*Temp;  for(N=top;N!=NULL;)//从表头开始删除  { Temp=N;     N=N->next;       deleteTemp;  }},,V>templatevoidStacklink::push(Typevalue)//进栈操作{ node*T;  T=newnode;//申请一个空间  if(T!=NULL)//判断申请是否成功  { T->next=top;//新申请的空间的指针域指向原栈顶元素     T->data=value;//新申请的空间的数据赋值       top=T;//栈指针指向新申请的空间  }  else  { cout<<"assignedfailure!";     exit(1);  }92 }templateintStacklink::isnull()//判栈空{ if(top->next==NULL)  return1;//如果链表中只剩一个结点(表头结点),栈为空返回1  else        return0;}templateTypeStacklink::pop()//退栈{ Typevalue;  node*Temp;  if(top->next==NULL)//判栈空  { cout<<"nthestackisNull!n";     return(0);  }  value=top->data;//取栈顶元素  Temp=top;//Temp指向栈顶元素  top=top->next;//Top指向栈顶元素的下一个元素  deleteTemp;//删除Temp指向的结点  return(value);//返回原栈顶元素}voidmain(){ intl=1,octal=0;  longdecimal,j;92   cout<<"npleaseinputinteger:";  cin>>decimal;//输入一个十进制数  j=decimal;  Stacklinkss;//定义一个整数栈  while(j!=0)  { ss.push(j%8*l);//将八进制的每一位数进栈     j=j/8;       l=l*10;  }  cout<#includetemplateclassnode{ public:    Typedata;       node*next;};templateclassStacklink{ public:    Stacklink();//构造函数       ~Stacklink();//析构函数       voidpush(Typevalue);//进栈       voidpop();//退栈       Typetopvalue();//取栈顶元素       intisnull();//判栈空private:92       node*top;};templateStacklink::Stacklink(){ node*T;  T=newnode;//申请一个空间  T->next=NULL;//指针项清0  top=T;//栈顶指针指向新申请的空间  //本例使用的是带头结点的单链表,第一个结点不会存储栈元素}templateStacklink::~Stacklink()//析构函数,删除单链表中的所有结点{ node*N,*Temp;  for(N=top;N!=NULL;)//从表头开始删除  { Temp=N;     N=N->next;       deleteTemp;  }}templatevoidStacklink::push(Typevalue)//进栈操作{ node*T;  T=newnode;//申请一个空间  if(T!=NULL)//判断申请是否成功  { T->next=top;//新申请的空间的指针域指向原栈顶元素92      T->data=value;//新申请的空间的数据赋值       top=T;//栈指针指向新申请的空间  }  else  { cout<<"assignedfailure!";     exit(1);  }}templateintStacklink::isnull()//判栈空{ if(top->next==NULL)  return1;//如果链表中只剩一个结点(表头结点),栈为空返回1  else        return0;}templatevoidStacklink::pop()//退栈{   node*Temp;  if(top->next==NULL)//判栈空  { cout<<"nthestackisNull!n";}     //value=top->data;//取栈顶元素  Temp=top;//Temp指向栈顶元素  top=top->next;//Top指向栈顶元素的下一个元素  deleteTemp;//删除Temp指向的结点92  //return(value);//返回原栈顶元素}templateTypeStacklink::topvalue(){      if(top->next==NULL)      { cout<<"nthestackisnull!n";        return(0);      }      returntop->data;}voidmain(){ inti=0;  chara[]="(a*(b+c)-b*d";  Stacklinkss;//定义一个字符栈  while(a[i]!="")//字符串未结束时循环  {         if(a[i]=="(")ss.push("(");//如果是左括号进栈        elseif(a[i]=="(")//否则,如果是右括号        {               if(ss.isnull())break;//如果栈空,退出循环               elseif(ss.topvalue()=="(")ss.pop();//否则如果栈顶元素是                                                    //左括号退栈        }        i++;92   }  if(ss.isnull()&&a[i]=="")//如果循环操作是结束于字符串终止符并且                               //栈空,说明括号匹配      cout<<"nmatch";  else        cout<<"nnotmatch"<#include#includetemplateclassnode{ public:    Typedata;       node*next;};templateclassqueuelink92 { public:    queuelink();       ~queuelink();       voidput(Typevalue);       Typeget();       voidclear();       voidshowqueue();private:      node*head;      node*rear;};templatequeuelink::queuelink(){ node*T;  T=newnode;  T->next=NULL;  head=rear=T;}templatequeuelink::~queuelink(){ node*N,*Temp;  for(N=rear;N!=NULL;)  { Temp=N;     N=N->next;       deleteTemp;92   }}templatevoidqueuelink::put(Typevalue){ node*T;  T=newnode;  T->next=NULL;  head->data=value;  head->next=T;  head=head->next;  cout<<"youhaveputadataintothequeue!n";}templateTypequeuelink::get(){ Typevalue;  node*T;  if(head==rear)  { cout<<"nThequeuehasnodata!n";     return(0);  }  value=rear->data;  T=rear;  rear=rear->next;  deleteT;  cout<<"nGet"<92 voidqueuelink::clear(){ head=rear;  cout<<"n***Queueisempty!***n";}templatevoidqueuelink::showqueue(){ node*T;  if(head==rear)  { cout<<"nthequeuehasnodata!";     return;  }  cout<<"nthecontentofqueue: n";  for(T=rear;T!=head;T=T->next)  cout<data;  cout<<"nn";}main(){ cout<<"

------putdatatoqueuen";  cout<<"------getdatafromqueuen";  cout<<"------clearqueuen";  cout<<"------showthecontentofqueuen";  cout<<"------quit......n";  queuelinkss;  charvalue;  charch;  while(1)  { cout<<"npleaseselectanitem:";     cin>>ch;92        ch=toupper(ch);       switch(ch)       { case"p":cout<<"nenterthevaluethat";                   cout<<"youwanttoput:";                            cin>>value;                            ss.put(value);                            break;          case"g":value=ss.get();                         break;              case"l":ss.clear();                         break;              case"s":ss.showqueue();                         break;              case"q":return(0);        default:cout<<"nyouhaveinputtedawrongitem!pleasetryagiain!n";               continue;       }  }}92 第九章:C++的输入输出[9_1]答:C++除了完全支持C语言的输入输出系统外,还定义了一套面向对象的输入输出系统。为什么C++还要建立自己的输入输出系统呢?这是因为在C++中需要定义众多的用户自定义类型,面向对象方法的数据封装性就是通过用户所定义的类类型来体现的,而继承性和多态性也是通过对用户定义的类对象的操作来体现的。但C语言的输入输出系统不支持用户自定义的类型。 [9_2]答:C++中包含几个预定义的流对象,它们是标准输入流(对象)cin(与标准输入设备相关联)、标准输出流(对象)cout(与标准输出设备相关联)、非缓冲型的标准出错流(对象)cerr(与标准错误输出设备相关联(非缓冲方式))。和缓冲型的标准出错流(对象)clog(与标准错误输出设备相关联(缓冲方式))。在缺省情况下,指定的标准输出设备是屏幕,标准输入设备是键盘。在任何情况下,指定的标准错误输出设备总是屏幕。[9_3]答:cerr和clog之间的区别是,cerr没有被缓冲,因而发送给它的任何内容都立即输出;相反,clog被缓冲,只有当缓冲区满时才进行输出,也可以通过刷新流的方式强迫刷新缓冲区。[9_4]答:C++提供了两种进行格式控制的方法:一种是使用ios类中有关格式控制的成员函数进行格式控制;另一种是使用称为操作符的特殊类型的函数进行格式控制。[9_5]答:C++中进行文件输入输出的基本过程是:必须首先创建一个流,然后将这个流与文件相关联,即打开文件,此时才能进行输入输出操作,操作完后再关闭这个文件。92 [9_6]以前介绍的文件操作都是按一定顺序进行读写的,因此称为顺序文件。对于顺序文件而言,只能按实际排列的顺序,一个一个地访问文件中的各个元素。为了增加对文件访问的灵活性,C++在类istream及类ostream中定义了几个与随机移动文件指针相关的成员函数,使得可以在输入输出流内随机移动文件指针,从而可以对文件的数据进行随机读写。[9_7]答:B[9_8]答:C[9_9]答:C  说明:dir的取值有3种:ios::beg ios::cur ios::end[9_10]答:A 说明:用ios::app打开的文件只能用于输出。[9_11]答:第一个width填5,第二个width填4[9_12]答:friendistream&operator>>(istream&in,Stock&st);        friendostream&operator<<(ostream&out,Stock&st);[9_13]答:#include#includedoublefact(intn);main(){ for(intn=5;n<11;n++)   cout<=1;i--)        factor*=i;  returnfactor;}[9_14]答:#include#includemain(){ doublex;92   cout.precision(5);  cout<<"x     lne     logx nn";  for(x=2.0;x<=10.0;x++)  { cout.width(2);     cout<#include#includeintmain(){ intflag=0,flag2=0;//flag==0表示前面的字符是空格                      //flag==1表示前面的字符是“is"  intsum=0;         //sum记录"is"的个数  charch;  fstreamin("file1.txt",ios::in);  if(!in)  { cerr<<"Erroropenfile.";     return0;  }  while((ch=in.get())!=EOF)        if(ch=="")92         { if(flag!=1)flag=1; }        else        { if(flag==1&&ch=="i")           flag2=1;           if(flag2==1&&ch=="s")              {sum++;                flag2=0;              }&nbp;             flag=0;        }        cout<#include#includemain(){ fstreamin("file1.txt",ios::in);  if(!in)  { cerr<<"Erroropenfile.";     return(0);  }  fstreamout("file2.tet",ios::out);  if(!out)  { cerr<<"Erroropenfile.";     return(0);92   }  charch;  while((ch=in.get())!=EOF)        out<#includemain(){ fstreamin;  in.open("file1.txt",ios::in);  if(!in)  { cerr<<"Erroropcnfllec.";     return(0);  }  fstreamout;  out.open("file2.txt",ios::app);  if(!out)  { cerr<<"Erroropenflle.";     return(0);  }  charch;  while((ch=in.get())!=EOF)        out<#includemain(){ ofstreampout("stock.txt");  if(!pout)  { cout<<"cannotopenphonefilen";     return1;  }  pout<<"shenfazhan000001n";  pout<<"shanghaiqiche600104n";  pout<<"guangjunengyuan000096n";  pout.close();  return0;}92'