C++第五章_类与对象习题解答
- 格式:doc
- 大小:37.50 KB
- 文档页数:6
1.什么是类的继承与派生?继承性是面向对象程序设计的第二个重要特性,通过继承实现了数据抽象基础上的代码重用。
继承是对许多问题中分层特性的一种自然描述,因而也是类的具体化和被重新利用的一种手段,它所表达的就是一种对象类之间的相交关系。
它使得某类对象可以继承另外一类对象的特征和能力。
继承所具有的作用有两个方面:一方面可以减少代码冗余;另一方面可以通过协调性来减少相互之间的接口和界面。
通过继承方式定义的子类也称为派生类。
2.类的三种继承方式之间的区别是什么?类的继承方式有public(公有)继承、protected(保护)继承和private(私有)继承三种。
对于不同的继承方式,会导致基类成员原来的访问属性在派生类中有所变化。
表5.1列出了不同继承方式下基类成员访问属性的变化情况。
表5.1 不同继承方式下基类成员的访问属性说明:该表第1列给出3种继承方式,第1行给出基类成员的3种访问属性。
其余单元格内容为基类成员在派生类中的访问属性。
从表中可以看出:(1) 基类的私有成员在派生类中均是不可访问的,它只能由基类的成员访问。
(2) 在公有继承方式下,基类中的公有成员和保护成员在派生类中的访问属性不变。
(3) 在保护继承方式下,基类中的公有成员和保护成员在派生类中均为保护的。
(4) 在私有继承方式下,基类中的公有成员和保护成员在派生类中均为私有的。
需要注意的是:保护成员与私有成员唯一的不同是当发生派生后,处在基类protected区的成员可被派生类直接访问,而私有成员在派生类中是不可访问的。
在同一类中私有成员和保护成员的用法完全一样。
3.派生类能否直接访问基类的私有成员?若否,应如何实现?派生类不能直接访问基类的私有成员。
具体实现方式:(1) 在类定义体中增加保护段为了便于派生类的访问,可以将基类私有成员中需提供给派生类访问的部分定义为保护段成员。
保护段成员可以被它的派生类访问,但是对于外界是隐藏起来的。
这样,既方便了派生类的访问,又禁止外界对它的派生类访问。
继承性是面向对象程序设计的第二个重要特性,通过继承实现了数据抽象基础上的代码重用。
继承是对许多问题中分层特性的一种自然描述,因而也是类的具体化和被重新利用的一种手段,它所表达的就是一种对象类之间的相交关系。
它使得某类对象可以继承另外一类对象的特征和能力。
继承所具有的作用有两个方面:一方面可以减少代码冗余;另一方面可以通过协调性来减少相互之间的接口和界面。
通过继承方式定义的子类也称为派生类。
5-2注意:(1)基类的私有成员在派生类中均是不可访问的,它只能由基类的成员访问。
(2)在公有继承方式下,基类中的公有成员和保护成员在派生类中的访问属性不变。
(3)在保护继承方式下,基类中的公有成员和保护成员在派生类中均为保护的。
(4)在私有继承方式下,基类中的公有成员和保护成员在派生类中均为私有的。
(5)保护成员与私有成员唯一的不同是当发生派生后,处在基类protected区的成员可被派生类直接访问,而私有成员在派生类中是不可访问的。
在同一类中私有成员和保护成员的用法完全一样。
5-3派生类不能直接访问基类的私有成员。
具体的实现方式有:(1)在类定义体中增加保护段为了便于派生类的访问,可以将基类私有成员中需提供给派生类访问的部分定义为保护段成员。
保护段成员可以被它的派生类访问,但是对于外界是隐藏起来的。
这样,既方便了派生类的访问,又禁止外界对它的派生类访问。
这种方式的缺点是在公有派生的情况下,如果把成员设为保护访问控制,则为外界访问基类的保护段成员提供了机会,而这三种派生方式,我们经常使用的是公有派生。
(2)将需访问基类私有成员的派生类成员函数声明为基类的友元这样派生类中的其他成员函数均无权访问它,外界不可能通过派生新类来达到访问基类私有成员的目的。
5-4构造函数的执行顺序:先祖先(基类)、再客人(对象成员),后自己(派生类本身)。
析构函数的执行顺序和构造函数正好严格相反:先自己(派生类本身),再客人(对象成员),后祖先(基类)。
Ch5 泛型与LINQ 习题解答1.假设Node类的每一个节点包括有两个字段:m_data(引用节点的数据)和m_next(引用链接列表中的下一项),这两个字段都是由构造函数方法设置的。
该类有两个功能,第1个功能是通过名为Data和Next的只读属性访问m_data和m_next字段,第2个功能是对System.Object的ToString虚拟方法进行重写。
试分别用类和泛型两种方法编写程序实现上述功能。
【解答】using System;class Node{Object m_data;Node m_next;public Node(Object data, Node next){m_data = data;m_next = next;}//访问结点数据public Object Data{get { return m_data; }}//访问下一个结点public Node Next{get { return m_next; }}// 获取结点数据描述public override String ToString(){return m_data.ToString();}}//链表结点类的泛型定义class Node<T>{T m_data;Node<T> m_next;public Node(T data, Node<T> next){m_data = data;m_next = next;}// 访问结点数据public T Data{get { return m_data; }set { m_data = value; }}// 访问下一个结点public Node<T> Next{get { return m_next; }set { m_next = value; }}// 获取结点数据描述public override String ToString(){return m_data.ToString();}}// 使用结点类型或泛型结点类型class LinkedList{static void Main(string[] args){//// 创建整数链表//Node head = new Node(5, null);//head = new Node(10, head);//head = new Node(15, head);////遍历链表求整数和//Int32 sum = 0;//for (Node current = head; current != null;// current = current.Next)//{// sum += (Int32)current.Data;//}//// 输出结果//Console.WriteLine("Sum of nodes = {0}", sum);// 用泛型创建整数链表Node<Int32> head = new Node<Int32>(5, null);head = new Node<Int32>(10, head);head = new Node<Int32>(15, head);// 遍历求和Int32 sum = 0;for (Node<Int32> current = head; current != null;current = current.Next){sum += current.Data;}// 输出Console.WriteLine("Sum of nodes = {0}", sum.ToString());}}2. 编写程序创建一个<int,string>的排序列表,向其添加5个元素后,按逆序方式显示列表中每一项的value值(string类型的值).【解答】using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ConsoleApplication{class Program{static void Main(string[] args){SortedList<int, string> list = new SortedList<int, string>();list.Add(10, "str10");list.Add(2, "str2");list.Add(13, "str13");list.Add(24, "str24");list.Add(15, "str15");for (int i = list.Keys.Count - 1; i >= 0; i--){Console.WriteLine(list[list.Keys[i]]);}Console.ReadLine();}}}3. 使用LINQ查询有哪些优势?什么是LINQ的延迟执行和立即执行?【解答】LINQ是一组查询技术的统称。
1:#include <iostream>using namespace std;class Student{public:void get_value(){cin>>num>>name>>sex;}void display( ){cout<<"num: "<<num<<endl;cout<<"name: "<<name<<endl;cout<<"sex: "<<sex<<endl;} private :int num;char name[10];char sex;};class Student1: public Student {public:void get_value_1(){get_value();cin>>age>>addr;}{ cout<<"age: "<<age<<endl; //引用派生类的私有成员,正确。
cout<<"address: "<<addr<<endl;} //引用派生类的私有成员,正确。
private:int age;char addr[30];};int main(){Student1 stud1;stud1.get_value_1();stud1.display();stud1.display_1();return 0;}2:#include <iostream>using namespace std;class Student{public:void get_value(){cin>>num>>name>>sex;}{cout<<"num: "<<num<<endl;cout<<"name: "<<name<<endl;cout<<"sex: "<<sex<<endl;}private :int num;char name[10];char sex;};class Student1: private Student{public:void get_value_1(){get_value();cin>>age>>addr;}void display_1(){display();cout<<"age: "<<age<<endl; //引用派生类的私有成员,正确。
实验六类与对象类是面向对彖程序设计中最棊木并H最重要的概念,也是面向对彖方法的第一个难点。
类是对逻辑上相关的函数与数据的封装,是对问题的抽象描述。
对象是类的实例化,是抽象的具体实现,类和对象的关系,是抽象与具体的关系,类概括出事物的木质特点,对象是对这些特点的具体体现。
实验目的和要求:1.掌握类和对象的使用。
2.掌握类的构造函数少析构函数。
3.掌握构造函数的重载。
4.了解拷贝构造两数的方法。
5.熟悉静态成员的使用和意义。
6.掌握友元的含义(友元函数、友元成员、友元类)。
7.掌握new和delete的使用。
实验内容:一、程序分析题1、写出以下程序的执行结果。
#include <iostream>using namespace std;class Tdcite{public:Tdate(){ Init(4,15,1995); }Tdate(int d){ lnit(4,d,1996); }Tdate(int m,int d){ Init(m,d,1997); }Tdate(int m,int d,int y){ Init(m,d,y); }protected:int month;int day;int year;void Init(int m,int djnt y){month=m; day=d; year=y;cout «month «H/M «day «,7M «year «endl;}};int main(){Tdate aday;Tdate bday(10);Tdate cday(2,12);Tdate dday( 1,2,1998);return 0;2、写出以下程序的执行结果。
#include <iostrcam> using namespace std;class MyClassf public:MyClass();MyClass(int);〜MyClass();void DisplayO;protected:int number;};MyClass::MyClass(){number =0;cout «n Constructing normallyAn*'; } MyClass::MyClass(int m):number(m){cout «n Constructing with a number: 4 5 6 7 8 9 10 11 «number «endl;}void MyClass::Display(){ cout «H Display a number: M «number «endl; } MyClass::〜MyClass(){ cout «H Destructing.\n n; }int main(){MyClass obj 1;MyClass obj2(20);objl.Display();obj2.Display();return 0;}3、写出以下程序的执行结果。
类和对象与运算符重载-答案选择题1、若有以下说明,在类外使用对象objx成员的正确语句是()。
class X{ int a;void fun1();public:void fun2();};A objx.a=0B objx.fun1();C objx.fun2();D X::fun1();2、若有以下说明,对n的正确访问语句是()。
class Y{ //………;public:static int n;};int Y::n=0;Y objy;A n=1;B Y::n=1;C objy::n=1;D Y->n=1;3、若有以下类Z的说明,函数fstatic的正确定义是()。
class Z{ int a;public:void fstatic(Z &)static;};A void Z::fstatic(Z &objz){objz.a=0;}B void Z::fs tatic(Z &objz){a=objz.a;}C void Z::fstatic(Z &objz){a=0;}D void Z::fstatic(Z &objz){Z::a=0;}4、若有以下类T的说明,函数ffriend的错误定义是()。
class T{ int i;friend void ffriend(T &,int);};A void ffriend(T &objt,int k){objt.i=k;}B void ffriend(T &objt,int k){k=objt.i;}C void T::ffriend(T &objt,int k){K+=objt.i;}D void ffriend(T &objt,int k){objt.i+=k;}5、在类定义的外部,可以被访问的成员有()。
A 所有类成员B 私有或保护类成员C公有的类成员 D 公有或私有的类成员6、关于this指针的说法正确的是()。
1、定义一个Date类。
#include <iostream>using namespace std;class Date{public:void Disp(){cout<<day<<'/'<<month<<'/'<<year;}void SetDate(int y,int m,int d){year=y;month=m;day=d;}void AddDay(){day++;}private:int year;int month;int day;};int main(){Date today,tomorrow;today.SetDate(2011,3,7);today.AddDay();tomorrow=today; // 将一个对象赋给同类型的另一个对象时,C++将源对象的每个数据成员的内容复制到目标对象中相应的数据成员中。
tomorrow.Disp();return 0;}2、定义一个Rectangle类。
(再将Rectangle类的定义放在一个头文件中,程序去调用这个头文件)#include <iostream>using namespace std;class Rectangle{public:Rectangle(double a=1,double b=1){length=a;width=b;}void SetValue(double m,double n){length=m;width=n;}double Perimeter(){return 2*(length+width);}double Area(){return length*width;}private:double length,width;};int main(){Rectangle r1,r2,r3(10,15);cout<<”the first rectangle:”<<endl;cout<<r1.Perimeter()<<endl;cout<<r1.Area()<<endl;cout<<”the second rectangle:”<<endl;r2.SetValue(10,20);cout<<r2.Perimeter()<<endl;cout<<r2.Area()<<endl;cout<<”the third rectangle:”<<endl;cout<<r3.Perimeter()<<endl;cout<<r3.Area()<<endl;return 0;}3、设计一个时间类Time。
第五章类与对象习题一.基本概念与基础知识自测题填空题引入类定义的关键字是(1)。
类的成员函数通常指定为(2),类的数据成员通常指定为(3)。
指定为(4)的类成员可以在类对象所在域中的任何位置访问它们。
通常用类的(5)成员表示类的属性,用类的(6)成员表示类的操作。
答案:(1)class(2)公有的public(3)私有的private(4)公有的public(5)数据(6)/(7)函数类的访问限定符包括(1)、(2)和(3)。
私有数据通常由(4)函数来访问(读和写)。
这些函数统称为(5)。
答案:(1)public(公有的)(2)private(私有的)(3)protected(保护的)(4)公有的成员函数(5)类的接口通常在逻辑上,同一类的每个对象都有(1)代码区,用以存储成员函数。
而在物理上通常只有(2)代码区。
只有在(3)定义,并(4)的函数和加了关键字(5)的函数例外。
答案:(1)?(2)独立的(3)共用的(4)在类说明中(5)不包括循环等复杂结构(6)inlineC++中支持三种域:(1)、(2)、(3)。
函数域被包括在(4)中,全局域被包括在(5)中。
using指示符以关键字using开头,后面是关键字(6),最后是(7)。
这样表示以后在该名字空间中所有成员都(8)。
如不使用using指示符则在使用时要加::,称为(9)运算符。
答案:(1)局部域(local scope)(2)名字空间域(namespace scope)(3)类域(class scope)(4)?(5)局部域(6)名字空间域(7)namespace(8)名字空间名(9)可以直接被使用(10)域引用通常用作函数的(1)和(2)。
对数组只能引用(3)不能引用(4)。
答案:(1)参数(2)返回值(3))(4)数组元素(5)数组名本身构造函数的任务是(1)和(2)。
构造函数无(3),但并不表示(4)。
类中可以有(5)个构造函数,它们由(6)区分。
如果类说明中没有给出构造函数,则C++编译器会(7)。
拷贝构造函数的参数是(8),当程序没有给出拷贝构造函数时,系统会自动提供(9)支持,这样的拷贝构造函数中每个类成员(10)。
答案:(1)建立对象(为对象分配内存)(2)初始化数据成员(3)函数返回类型说明(4)没有返回值,返回的是构造函数所创建的对象(5)多(6)不同的参数表(7)-(8)自动给出一个缺省的构造函数(9)同一类对象的引用(10)缺省的拷贝构造函,称为缺省的按成员语义支持。
(11)被依次拷贝一个类有(1)个析构函数。
(2)时,系统会自动调用析构函数。
答案:(1)一(2)对象注销时运算符重载时,其函数名由(1)构成。
成员函数重载双目运算符时,左操作数是(2),右操作数是(3)。
答案:(1)@(2)关键字operator和该运算符(3)对象(4)该函数的参数5.2简答题(以下习题题号可能和教材不一致!)5.2.1为什么返回值为引用的函数可以作为左值答:函数返回引用实际是指明(返回)了相应的关联变量,所以声明返回值为引用的函数实际上是将关联变量作为左值参与运算。
5.2.2什么是缺省的构造函数缺省的构造函数最多可以有多少个&答:如果在类定义中不显式地定义构造函数,C++编译器会自动产生一个缺省的构造函数,不过该函数不做具体的初始化工作。
只要构造函数是无参的或者只要各参数均有缺省值的,C++编译器都认为是缺省的构造函数。
缺省的构造函数只能有一个。
5.2.3拷贝构造函数用于哪三个方面答:(1)用类的一个对象去初始化该类的另一个对象时使用。
(2)当函数的形参是类的对象,调用函数时,进行形参与实参结合时使用。
(3)当函数的返回值是类对象,函数执行结束返回调用者时使用。
5.2.4所有类对象未重载的赋值运算符“=”是怎样工作的为什么它可以进行连续赋值答:对所有的类对象,未重载的赋值运算符“=”称作缺省的按成员拷贝赋值操作符,同类对象之间可以用“=”直接拷贝。
因为缺省的赋值操作返回一个对象的引用,所以它可以进行连续赋值。
[5.2.5为什么在友元函数的函数体内访问对象成员时,必须用对象名加运算符“.”再加对象成员名答:友元函数不是类的成员函数,在函数体中访问对象的成员,必须用对象名加运算符“.”加对象成员名。
这一点和一般函数一样。
5.2.6重载复数运算符+时,采用下面友元函数声明:friend Complex operator+(Complex &c1,Complex &c2);为什么不能用于“实数+复数”怎样改进才能适用为什么答:使用引用类型变量作为运算符重载函数的参数,身为左值的实数类型实参不能被转换为复数,编译时无法通过。
添加const说明,使实数到复数的转换隐式地在一份拷贝上进行,则可以实现“实数+复数”运算。
修改后的说明为:friend Complex operator+(constr Complex &c1, const Complex &c2);5.2.7·5.2.8C++中结构、联合与类三者间有何异同答:在C++中结构(structure)与类几乎是完全一样的类型,差别仅仅在于缺省情况下结构的成员为公有的。
联合(union)是C++的导出数据类型,在语法与功能上类似于结构,二者的区别是:结构变量的各成员同时被分配了各自独立的内存区,而联合变量的各个成员的存储开始地址都相同,所以在任一时刻联合变量只能存储一个成员。
二.编程与综合练习题构造一个日期时间类(Timedate),数据成员包括年、月、日和时、分、秒,函数成员包括设置日期时间和输出时间,其中年、月请用枚举类型,并完成测试。
(包括用成员函数和用普通函数)解:本题要求仅是定义类的练习,并非实用的提供日期时间的程序。
实用的日期时间程序见附录二的日期时间函数。
#include <>#include <>#include <>enum YR{Y2000,Y2001,Y2002,Y2003,Y2004,Y2005};`Circumference=2*r*3.;}Circle::Circle(Circle & cl){r=;Area=;Circumference=;}void Circle::SetR(double R){r=R;《Area=r*r*3.;Circumference=2*r*3.;}void main(){Circle cl1(2),cl2,cl3=cl1;cout<<"圆半径:"<<()<<'\t'<<"圆周长:"<<()<<'\t'<<"圆面积:"<<()<<endl;(4);cout<<"圆半径:"<<()<<'\t'<<"圆周长:"<<()<<'\t'<<"圆面积:"<<()<<endl;.}5.4设计一个学校在册人员类(Person)。
数据成员包括:身份证号(IdPerson),姓名(Name),性别(Sex),生日(Birthday)和家庭住址(HomeAddress)。
成员函数包括人员信息的录入和显示。
还包括构造函数与拷贝构造函数。
设计一个合适的初始值。
解:本题为指出构造函数等的调用,加了一些提示语句。
#include<>#include<>enum Tsex{mid,man,woman};class Person{char IdPerson[19];假设某城市人人所得税的税基为2000元,而其征收个人所得税的规定如下:不超过税基免征税,按超过税基部分征收所得税。
超过部分在2000元以下,征税5%;5000元以下,征税10%;10000元以下,征税15%;10000元以上,征税20%。
建立一个incomec类,共包含的数据成员和成员函数如下:\income数据成员,表示职工的实际收wage静态数据成员,表示职工工资taxrate静态数据成员,表示税率setWage(double m)成员函数,设置工资值getTaxrate()静态成员函数,计算税率calIncome()静态成员函数,计算职工的实际收入在主函数中,实例化不同的incomec类对象,并计算它们的实际收入。
#include<iostream>using namespace std;class incomec{private:float income;static float wage;static float taxrate;public:incomec(){income=0;}void setWage(double);static float getTaxrate();static void callcome();};float incomec::taxrate=;float incomec::wage=3000;void incomec::setWage(double w){wage=w;}void incomec::callcome(){float all,super;super=wage-2000;all=2000+super*(1-getTaxrate());cout<<"职工的实际工资为:"<<all<<endl;cout<<endl;}float incomec::getTaxrate() {float left=wage-2000;if(left<2000){taxrate=;}else if(left<5000){taxrate=;}else if(left<10000){taxrate=;}else{taxrate=;}return taxrate;}void main(){incomec a1;(20000);();incomec a2;(20000);cout<<"税率为:"<<()<<endl; ();}。