LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1817|回复: 30

帮我做几道题目 谢谢了

[复制链接]
发表于 2004-5-1 11:22:41 | 显示全部楼层 |阅读模式
最初由 ltkun 发表
1 请回答,下面程序的执行结果为什么不是:
B: b=77
C: c=999
C: c=999
而是:
B: b=77
C: c=145
C: c=145

#include<iostream.h>
class A{ public:
           virtual void show(int a=145){cout<<"A: a="<<a<<endl; }   
        };
class B:public A
       { public:
           void show(int b){ cout<<"B: b="<<b<<endl; }
       };
class C:public B
       { public:
           void show(int c=999){ cout<<"C: c="<<c<<endl; }
       };
class D:public C
       { public:
void show(){ cout<<"D:\n"; }
       };
void main()
{ A a,*pa=&a;
  B b; C c; D d;
  pa=&b; pa->show(77);
  pa=&c; pa->show();
  pa=&d; pa->show();
} /*执行结果:B: b=77
              C: c=145
              C: c=145    */









2 下面程序的执行结果的最后一行为什么不是:base1: a=3 b=9? 而是base1: a=0 b=0?
#include<iostream.h>
class base1{   int a,b;
             public:
               base1(int aa=0,int bb=0)  //构造函数
                { a=aa; b=bb;
                  cout<<"base1  class!"<<endl; }
               void show(){ cout<<"base1: a="<<a<<" b="<<b<<endl; }
           };
class base2{ public:
               base2(){ cout<<"base2  class!"<<endl; }
               void show2(){ cout<<"base2:  "<<endl; }
           };
class level1:public base2,virtual public base1
            { public:
                level1(int a,int b):base1(a,b)
                  { cout<<"level1 class!"<<endl; }
            };
class level2:public base2,virtual public base1
            { public:
                level2(int a,int b):base1(a,b)
                  { cout<<"level2 class!"<<endl; }
            };
class lastlevel:public level1,virtual public level2
            { public:
                lastlevel(int a,int b):level1(a,b),level2(a,b)
                  { cout<<"lastlevel class!"<<endl; }
            };
void main()
{ lastlevel obj(3,9);
  obj.show();    //直接调用间接基类base的公有成员函数show()
}/*执行结果:base1  class!
base2  class!
level2 class!
base2  class!
level1 class!
lastlevel class!
base1: a=0 b=0     */












二 简答题(每小题5分,共10分)
1 学校有关教学人员的信息可以分为“学生”和“教师”两大类,而学生(Student)和教师(Teacher)都属于“人”(People)类,可以从People类继承。学校中有在职博士生(Doctor_Teacher),他们既是教师,同时又是攻读博士学位的学生。因此,Doctor_Teacher类可以从Student和Teacher类继承。现有如下两种不同的继承方式(继承结构图分别为case1和case2),请描述这2种继承各有什么不同?





2 对于上面第1小题的4个类:People、Teacher、Student、Doctor_Teacher,如果让你把其中一个类定义成抽象类,你定义哪一个类?为什么?






三 选择题(每空1分,共10分)
1  编写程序时,尽可能做到         。
⑴ 程序的语句数越少越好         ⑵ 循环语句尽量不用   
⑶ 提高程序的可读性             ⑷ 减少函数被调用的次数
⑵ 只要语句不多于10条的函数都可以定义成内联函数。
⑶ 语句少的构造函数最好定义成内联函数,可以提高效率。
⑷ 内联函数可以免去函数调用的开销。
⑸ 把那些调用不频繁的函数定义成内联函数可以提高程序运行效率。
2 一个数组所占有的内存空间是       的。
⑴ 连续   ⑵ 不连续   ⑶ 随机分配   ⑷ 小的数组是连续的、大的数组可以是不连续
3 用new创建的局部动态对象的作用域是        。
⑴ 局部作用域   ⑵ 函数作用域   ⑶ 文件作用域   ⑷ 函数原型作用域
4 如果Student类继承于People类,下面       说法是正确的。
⑴ Student 类包含了People类的全部成员。      
⑵ Student类的对象包含了People的全部数据成员。
⑶ Student类的对象包含People的哪些成员,取决于继承类别。
⑷ 如果Student类私有继承了People类,则Student类的对象中就不包含People类的私有成员。
5 抽象类的构造函数不能定义成       的。
⑴ public      ⑵ private    ⑶ protected
6 把某一个类设计成抽象类的主要目的是       。
⑴ 拒绝用户定义对象。      
⑵ 为众多派生类指定统一的公共接口,使得派生类不必再编写这些接口代码。
⑶ 使得在继承时不必考虑抽象父类的数据结构,因为抽象父类不能定义对象。
⑷ 为众多派生类指定统一的公共接口。
7 关于抽象类,下面       说法是正确的。
⑴ 因为抽象类不能定义对象,所以抽象类只能做父类、不能做派生类。      
⑵ 因为抽象类不能定义对象,所以抽象类中不能有数据成员。
⑶ 因为抽象类不能定义对象,所以抽象类不可以是函数的返回类型。
⑷ 因为抽象类不能定义对象,所以尽管抽象类中有数据成员,抽象类的派生类对象中不继承抽象类的数据成员。
8 因为友元成员不是本类的成员,所以       。
⑴ 友元成员没有对应的this指针。      
⑵ 友元不能访问本类的父类的任何成员。
⑶ 友元不能修改本类数据成员。
⑷ 友元至少有一个参数,而且其类型是本类型。
9 一个被调用的inline函数的定义与调用该inline函数的函数分别写在不同的源文件中,如果inline函数的代码一旦有所改变,下面        说法是正确的。
⑴ 所有调用该函数的代码必须重新编译。
⑵ 只要重新编译该inline函数即可,所有调用该函数的代码不必重新编译。
⑶ inline函数和调用该函数的代码都不必重新编译,因为inline函数实际上不是函数。
⑷ 因为inline函数实际上不是函数,所以inline函数的代码是否改变无关紧要。
10基类的析构函数最好定义成虚函数,因为        。
⑴ 在进行多态处理时,基类的析构函数如果不是虚函数,就无法析构派生类对象。
⑵ 在进行多态处理时,不需要调用父类的析构函数。
⑶ 父类的虚函数可以被继承。
⑷ 虚函数可以被派生类重载。



四 填充题(每小题1分,共10分)
1 在C++ 中,不同类型的指针之间不能相互赋值,但只有          类型的指针例外。
2 在C++ 中,指针的值不是整型,所以整型数据不能赋值给指针,但只有整型数     可以赋值给任何类型的指针。
3 用new创建的、由局部指针对象指出的对象的作用域是           。
4 在类的成员函数中,什么被认为是隐含的内联函数?           成员函数。
5 一个声明、后定义的函数,如果要使其成为内联函数,则必须在       时冠以inline,否则编译程序不认为是内联函数。     
6 对于有继承关系的类,父类子对象的初始化只能在直接派生类的               中进行,而不可以在直接派生类的构造函数的函数体中进行。
7 一个函数的             ,实际上是起到多个函数重载的作用。
8 在C++ 异常处理机制中,被throw语句抛出的异常,只有当该throw语句在       语句块的控制范围内,才会被捕获。
9 某个操作符重载后,其原来的优先级和结合性            。
10父类的指针指向派生类的对象,以实现                。


五 是非题(每小题1分,共10分)
1 一个类的所有对象都具有相同的数据结构和操作。
⑴  是      ⑵  非
2 类的static成员不是属于某个对象的、而是所有对象共享的,因此系统对具有static成员的类就不提供this指针。
⑴  是      ⑵  非
3 在同一程序中的所有同名函数都是函数重载。
⑴  是      ⑵  非
4 纯虚函数绝对不可以有函数定义。
⑴  是      ⑵  非
5 int x=7,&xx=x; 此xx是x的“引用”,系统不为xx分配整型数据的内存空间,所以xx不可以做左值。
⑴  是      ⑵  非
6 构造函数的作用是创建和初始化对象,而构造函数又是公有成员函数,所以,要创建多个新的对象,只要通过某个对象多次调用构造函数即可。
⑴  是      ⑵  非
7 析构函数的作用是“消除”对象,因此,如果要使某个对象“消失”,只要调用析构函数即可。
⑴  是      ⑵  非
8 一个对象可以有多个“引用”。
⑴  是      ⑵  非
9 加以const限定的对象是常量,所以不能对const对象进行取址。
⑴  是      ⑵  非
10 C++允许一行写多条语句,但是预编译指令必须单独占有一行。
⑴  是      ⑵  非



六 编程题(共30分)
现有如下的main()函数,成员函数的功能见说明。请用面向对象的软件“复用”技术设计并定义Shape、Point、Triangle、Rectangle、Cubic,致使能正确运行如下的main()函数。说明:
函数getTypeName()  的功能是输出pS所指向的对象的类型名;
函数pS->getValue() 的功能是输出pS指向的对象的数据成员值;               
函数pS->calArea()  的功能是计算并输出pS指向的对象的面积;
函数pS->calVolume() 的功能是计算并输出pS指向的对象的体积。                          

void main()
{  Shape* pS = NULL;                         //定义Shape类的指针pS
//创建4个点(2个数据分别为x,y的坐标值):
Point p1(0,0),p2(100,0),p3(100,50),p4(0,50);
Triangle t1(p1,p2,p3);                    //用3点创建一个三角形对象
Rectangle r1(p1,p2,p3,p4);                //用4点创建一个矩形对象
int h=100 ;
Cubic c1(p1,p2,p3,p4,h);                  //创建一个立方体对象,h为高
pS = &p1;                                 //指针pS指向Point的对象p1                     
pS->getTypeName();                         
pS->getValue();                                           
pS = &t1;                                   
pS->getTypeName();                          
pS->getValue();                                           
pS->calArea();                             
pS->calVolume();                                                     
pS = &r1;                                   
pS->getTypeName();                          
pS->getValue();                           
pS->calArea();
pS->calVolume();                           
pS = &c1;                                   
pS->getTypeName();                          
pS->getValue();                           
pS->calArea();
pS->calVolume();                           
}
//注意:输出结果必须可理解。
发表于 2004-5-1 13:12:19 | 显示全部楼层
今天五一, 你就别出难题了, 让大家过个开心的节日吧

PS:可以在这里找枪手的吗?
发表于 2004-5-1 13:21:35 | 显示全部楼层
晕,好长啊
灰了
 楼主| 发表于 2004-5-1 14:27:57 | 显示全部楼层
最初由 茜如和小劲鸭 发表
今天五一, 你就别出难题了, 让大家过个开心的节日吧

PS:可以在这里找枪手的吗?


可以,用任何的方法。。。:p
发表于 2004-5-1 15:55:30 | 显示全部楼层
为什么把作业 放在这里?

你可以 问问算法 什么得,不要把老师得作业拿出来让大家做

! 这样会害了自己得!
发表于 2004-5-2 00:23:16 | 显示全部楼层
这可能不是一般的考试,题目是真难.我最多能做对一半.呵呵...
发表于 2004-5-2 10:24:59 | 显示全部楼层
第一题这是我从昨天想到今天才明白的,呵呵...)
这个问题要分成静态语义和动态语义两个部分来理解,必须对编译原理和c++的对象模型有所了解才能给出正确答案. 静态语义就是在编译时能够确定的语义, 比如说函数参数的缺省值, 在这里基类A.show(int a = 145)的函数参数的缺省值就是145, 如果用A *pa; pa->show();调用不给参数的show()函数, 运行结果肯定是打印出145, 这没有什么可说的. 这种缺省值在编译时就已经由编译器插入到汇编代码中了,因此函数的缺省参数是在编译阶段静态确定的,也就是说只要有pa->show();有地方,编译器都会把A中show()函数的缺省值作为默认参数来处理. 自然下面这段代码中所有的默认值也被编译器处理成145啦.
  1. pa = &c;  
  2. pa->show ();
  3.   pa = &d;
  4.   pa->show ();
复制代码
在另一方面, c++由于采用了动态捆绑(dynamic binding)作为多态的实现机制,动态捆绑以称为晚捆绑(late binding),是一种在运行时动态确定语义的机制. 编译器在编译时并不知道基类指针可以会指向具体的那一个派生类对象, 所以具体执行那个派生类对象的show()函数,是在运行时动态确定的. 如果在运行时pa = &c;   pa->show (); 那么基类指针实际上是指向它的派生类C的一个对象实例c, 因此应付实际调用c的show()方法而不是基类A的show()方法.
在明白以上两点之后, 我们就知道,已经在编译时静态确定的参数缺省值和动态确定的show()方法在运行时结合后,就会产生出B: b=77  C: c=145
C: c=145 这种派生类的函数输出基类参数缺省值的运行结果了.说得通俗一点, 就是所有pa->show()函数在运行之前, 它的参数值已经被编译器确定为145, 只不过在运行时具体调用某个派生类的show()来显示这个值而已.
发表于 2004-5-2 10:51:30 | 显示全部楼层
大家谈谈自己的看法吧. 我感觉说得还不够透彻, 全面.
 楼主| 发表于 2004-5-2 11:46:34 | 显示全部楼层
哦~~这个。。。不懂。。。:p
发表于 2004-5-2 12:35:43 | 显示全部楼层
我觉得还要考虑到那个virtual的用法。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表