第9章 继承和派生习题(详解)

在这里插入图片描述

一、选择题

1.下列表示引用的方法中, () 是正确的。已知:int m=10:

A.int &x=m; B.int &y=10; C.int &z; D.float &t=&m;

在C++中,引用是一个变量的别名。正确的引用声明方式应遵循C++的引用规则。选项分析:A.`int &x=m;` 这是一个正确的引用声明。`x` 成为 `m` 的引用,`x` 和 `m` 指向同一内存位置。B.`int &y=10;` 这是一个错误的引用声明。引用必须绑定到一个变量,不能直接绑定到字面值(如10)。C.`int &z;` 这是一个错误的声明。引用在声明时必须被初始化。D.`float &t=&m;` 这是一个错误的声明。首先,`&m` 获得的是变量 `m` 的地址,其类型是 `int*` 而不是 `float`。其次,`t` 应该直接绑定到一个 `float` 类型的变量,而不是一个地址。因此,正确的选项是:A.`int &x=m;`

2. 在以下类定义中, () 的虚基类

A)类B、类C是类A B)类A是类B、类C C)类B、类C是类D D)类A是类D

class A{
public: 
int x;
A(int a=0){x=a;}};
class B:public virtual A
{ ... };
class C:virtual public A
{  ... };
class D:public B,public C
{   	A x; 
public: 
int m; 
D(int a,int b,int c):B(a),C(b),x(c)  //F
...
};
在C++中,如果一个基类被多个直接或间接派生类通过不同的路径继承,
并且这个基类在继承路径中至少有一次是作为虚基类来继承的,那么这个基类就是虚基类。
如果一个基类包含另一个基类的指针或引用,那么这个基类就被称为虚基类。 选D

3.C++中的类有两种用法:一种是类的实例化,即生成类的对象,并参与系统的运行;另一种是通过 (),派生出新的类。

A.复用 B.继承C.单继承 D.多继承

继承允许新的类接收(或继承)一个或多个类的成员(包括数据成员和成员函数)。
这是代码复用的一个主要手段。选B

4.继承具有 () ,即当基类本身也是某一个类的派生类时,底层的派生类也会自动继承间接基类的成员。

A.规律性 B.传递性 C.重复性 D.多样性

B.传递性
这个特性确保了派生类能够从它的直接基类以及间接基类那里继承属性和方法,允许多层次的抽象和代码重用。

5.在多继承中,公有派生和私有派生对于基类成员在派生类中的可访问性与单继承的规则 () 。

A.完全相同 B.完全不同 C.部分相同,部分不同 D.以上都不对

在多继承中,公有派生和私有派生对于基类成员在派生类中的可访问性的规则与单继承中的规则是完全相同的。
无论是单继承还是多继承,
基类成员的访问控制(public, protected, private)都遵循相同的规则。因此,正确的答案是:
A.完全相同
公有继承(public inheritance)意味着基类的公有成员和保护成员在派生类中保持原有的访问权限,
而私有继承(private inheritance)意味着基类的所有成员在派生类中都变成了私有成员,
无论它们在基类中原来是什么访问权限。

6.派生类的构造函数的成员初始化列表中,不能包含 。

A.基类的构造函数 B.派生类中子对象的初始化
C.基类的子对象初始化 D.派生类中一般数据成员的初始化

在派生类的构造函数的成员初始化列表中可以包含以下元素:
A. 基类的构造函数 - 派生类的构造函数可以(并且在多数情况下应该)
在其成员初始化列表中调用基类的构造函数,以确保基类部分被正确初始化。
B. 派生类中子对象的初始化 - 如果派生类有类类型的成员(子对象),
则可以(也应该)在成员初始化列表中初始化它们。
C. 基类的子对象初始化 - 这一选项是有歧义的。如果指的是基类的成员(即基类中的子对象)
,那么这些在基类构造函数中被初始化,不应直接出现在派生类的成员初始化列表中。
但是,如果这里指的是由基类派生出的另一个基类的对象,
则派生类可以在其成员初始化列表中直接初始化这样的基类的子对象。
D. 派生类中一般数据成员的初始化 -派生类的构造函数的成员初始化列表当然可以包含派生类中一般数据成员的初始化。
因此,如果我们解释C为“基类中的子对象”,那么它是不能被派生类的构造函数的成员初始化列表直接初始化的,因为这是基类构造函数的责任。这样看来,C是正确的答案。如果解释C为“由基类派生的其他基类”,那么派生类是可以(并且应该)在其成员初始化列表中初始化这样的对象的。这里需要明确题目中“基类的子对象初始化”的具体含义。
选C

7. 定义派生类时,若不使用关键字显式地规定采用何种继承方式,则默认方式是 。

A. 私有继承 B. 非私有继承 C. 保护继承 D. 公有继承

A 私有继承

8. 在一个派生类的成员函数中,试图调用其基类的成员函数“void f();”,但无法通过编译。这说明 () 。

A. f()是基类的私有成员 B. f()是基类的保护成员
C. 派生类的继承方式是私有 D. 派生类的继承方式为保护

A f()是基类的私有成员

9. 有如下类定义:

class AA{
int a;
public:
AA(int n=0):a(n){}
};
class BB:public AA{
public;
BB(int n).......};

其中横线处缺失部分是 。
A.:a(n){} B.;AA(n){} C.{a(n)}; D.{a=n};

选项B `:AA(n){}` 正确的填写了类 BB 的构造函数,在初始化列表中调用了基类 AA 的构造函数,将 n 作为参数传递给它。这是正确的继承和初始化方式,能够确保派生类 BB 创建时,其基类 AA 的部分也得到了正确的初始化。以下是各个选项的解释:A. `:a(n){}` - 这是不合法的,因为 `a` 是基类 AA 的私有成员,不可以在派生类的初始化列表中直接初始化。B. `:AA(n){}` - 这是正确的。它使用基类的构造函数来初始化基类部分。C. `{a(n)};` - 这也是不合法的,因为像选项 A,`a` 是私有成员,不能在派生类中直接初始化或访问。D. `{a=n};` - 这同样是不合法的,因为 `a` 是基类的私有成员,不能在派生类中直接赋值。因此,正确答案是 B,它正确地使用了基类构造函数初始化基类成员变量。

10. 已知基类 Employee只有一个构造函数,其定义如下:

Employee::Employee(int n):id(n){}
Manager 是 Employee 的派生类,则下列对 Manager 的构造函数定义中,正确的是 。
A.Manager::Manager(int n):id(n){}
B.Manager::Manager(int n){id=n}
C.Manager::Manager(int n):Employee(n){}
D.Manager::Manager(int n){ Employee(n);}

C

11.有如下程序:

#include<iostream>
using namespace std;
class Base{
public;
void fun(){cout<'B';  }
};
class  Derived:public  Base{
public:
void fun()
{   .......        ;                                              
cout<<'D';
}
};
int main()
{  	Derived d;
d.fun();
return 0;
}

若程序的输出结果是 BD, 则画线处缺失的部分是 。
A.fun(); B.Base,fun(); C.Base::fun(); D.Base->fun();

C

12. 关于虚基类的描述中,错误的是 () 。

A, 使用虚基类可以消除由多继承产生的二义性
B. 构造派生类对象时,虚基类的构造函数只被调用一次
C. 声明“class B:virtual public A”,说明类 B为虚基类
D. 建立派生类对象时,首先调用虚基类的构造函数

C. 声明“class B:virtual public A”,说明类 B为虚基类这个描述是错误的。该声明实际上是指 A 是 B 的虚基类,而不是 B 是某个虚基类。当使用虚继承时,
类 A 将成为类 B 的虚基类,这样做是为了解决多重继承中可能出现的菱形继承问题,
其中一个类可能通过不同的路径多次继承同一个基类。

二、填空题

1. 如果类 A 继承了类 B, 那么类 A 被称为 (基) 类,而类 B 被称为 (派生) 类。
2 . C++的两种继承为: (公有继承) 和 (私有继承) 。
3. 在默认情况下的继承方式为(私有继承) 。
4. 从基类中公有派生一个类时,基类的公有成员就成为派生类的(公有) 成员,而这个基类的保护成员就成为派生类的 (保护) 成员。
5. C++提供了(多继承) 机制,允许一个派生类可以继承多个基类,甚至这些基类是互 不相关的。
6. 类X中的名字N 支配类Y中同名的名字N, 是指类X 以类Y 为它的一个基类,这称为 (支配规则) 。
7. 引进虚基类的目的是 (消除多重继承中由于继承同一个基类而产生的二义性和重复基类成员问题) 。
8. 在一个继承结构中,解决二义性的方法有 (虚继承) 和 (使用作用域运算符) 。

三、阅读程序题

1. 下列程序的输出结果是(3)

#include<iostream>
using namespace std;
class Base
{	int k;
public:void set(int n){k=n;}int get(){return k;}
};
class Derived:protected Base
{  	int j;
public:void set(int m,int n){Base::set(m);j=n;}int get(){return Base::get()+j; }
};
int main()
{Derived d;d.set(1,2);cout<<d.get()<<endl;return 0;
}

2,下列程序的输出结果是

#include<iostream>
using namespace std;
class A
{
public:A(){ cout<<"A";}~A(){cout<<"~A"; }
};
class B:public A
{	A *p;
public:B(){   cout<<"B";p=new A();}~B(){   cout<<"~B";delete p;}
};
int main()
{  	B obj;return 0;
}
程序的输出结果是 `ABAB~A~B~A`。下面是程序执行过程中的详细解释:1. 在main函数中,创建了一个`B`类的对象`obj`。
2. 调用`B`的构造函数`B()`,由于`B`继承自`A`,首先调用基类`A`的构造函数。
3. 输出`A`。
4. 然后执行`B`的构造函数体,输出`B`。
5. 在`B`的构造函数中,使用`new`创建了一个`A`类的对象,并将其地址赋值给指针`p`,因此会再次调用`A`的构造函数。
6. 输出`A`。
7. 程序接着会离开`B`构造函数的作用域,但此时对象`obj`的生命周期并未结束,故不会调用任何析构函数。
8. 当main函数执行完毕,`obj`的生命周期结束,此时会首先调用`B`类的析构函数`~B()`。
9. 输出`~B`。
10. 在`~B()`中,`delete p;`会删除之前构造函数中创建的`A`对象,因此调用`A`的析构函数。
11. 输出`~A`。
12. 跳出`~B()`的作用域,`B`的析构函数执行完毕,接着调用基类`A`的析构函数。
13. 输出`~A`。因此,整个程序的输出为`ABAB~A~B~A~A`。

3. 下列程序的输出结果是 。

#include<iostream>
using namespace std;
class A{
public:int x;A(){ x=100; }A(int  i){x=i; }void Show(){ cout<<"x="<<x<<'\t'<<"AA\n"; }
};
class B{
public:int y;B(){y=300;}B(int x){y=x; }void Show(){cout<<"y="<<y<<'\t'<<"BB\n";}
};
class C:public A,public B{
public:int y;C(int a,int b,int c):A(a),B(b){y=c; }void Show(){ cout<<"y="<<y<<'\t'<<"cc\n"; }
};
int  main()
{  	C c1(400,500,600);c1.y=200;c1.Show();c1.A::Show();c1.B::Show();return 0;
}

4. 下列程序的输出结果是

#include<iostream>
using namespace std;
class base
{
public:void who(){ cout<<"base class"<<endl;}
};
class derivel:public base
{
public:void who(){cout<<"derivel class"<<endl;}
};
class derive2:public base
{
public:void who(){cout<<"derive2 class"<<endl; }
};
void fun(base *p)
{   p->who();}
int main()
{   base obj1,*p;derivel obj2;derive2 obj3;fun(&obj1);fun(&obj2);fun(&obj3);obj2.who();obj3.who();return 0;
}
base class
base class
base class
derivel class
derive2 class
程序解释:base obj1,*p; 声明了基类 base 的一个对象 obj1 和一个指针 p。derivel obj2; 声明了派生类 derivel 的一个对象 obj2。derive2 obj3; 声明了派生类 derive2 的一个对象 obj3。fun(&obj1); 调用函数 fun 传入 base 类的对象地址,函数中的 p->who(); 调用的是基类 base 的 who 方法。fun(&obj2);fun(&obj3); 由于 fun 的参数类型是 base 类的指针,根据参数的静态类型,调用的也是 base 类的 who 方法。这里没有发生多态,因为 who 方法在基类中没有被声明为 virtual。最后,obj2.who(); 和 obj3.who(); 直接调用其各自类的 who 方法,因为这里是通过对象调用,不涉及多态。由于基类的 who() 方法没有被声明为虚函数 (virtual)fun() 函数中的 p->who() 调用不会展现多态行为(即不会根据对象的实际类型来调用对应的函数),而是会根据指针类型(基类 base)调用基类的 who() 方法。因此,前三次调用 fun() 都会输出 "base class"。而直接通过派生类对象调用 who() 时,则会调用相应派生类中的方法,分别输出 "derivel class""derive2 class"

三、编程题

1. 定义一个长方形 Rect 类,派生出长方体类 Cub, 计算派生类对象的表面积和体积。

#include <iostream>
using namespace std;
class Rect{public:double length;double width;Rect(double l,double w){length=l;width=w;}double area1(){return length*width;}
}; 
class Cub:public Rect{double height;public:Cub(double l,double w,double r):Rect(l,w){height=r;}double bs(){return 2*length*width+2*length*height+2*width*height;}double volume(){return area1()*height;}
};
int main(){Cub A(3,4,5);cout<<"表面积为:"<<A.bs()<<"体积为:"<<A.volume();
}
}

在这里插入图片描述

2. 定义一个 Shape 基类,并派生出圆球体(Sphere) 和立方体类(Cube), 分别求圆球体 与立方体对象的表面积和体积。

#include<iostream>
using namespace std;
class Shape {
protected: // protected允许子类访问double x, y;
public:Shape(double a, double b) {x=a;y=b;}double area() {return 0;} double volume() {return 0;}
};
class Sphere : public Shape {double radius;
public:Sphere(double d): Shape(d, d){radius=d;} // 调用基类构造函数并初始化radiusdouble area() {return 3.14 * radius * radius * 4;}double volume() {return 3.14 * radius * radius * radius * 4 / 3;}
};
class Cube : public Shape {double z;
public:Cube(double a, double b, double c) : Shape(a, b) {z=c;} // 调用基类构造函数并初始化zdouble area() {return 2 * (x * y + x * z + y * z);}double volume() {return x * y * z;}
};
int main() {Sphere A(1);cout << "圆球体的表面积为:" << A.area() << "\n"; cout << "圆球体的体积为:" << A.volume() << "\n"; Cube B(3, 4, 5);cout << "立方体的表面积为:" << B.area() << "\n"; cout << "立方体的体积为:" << B.volume() << "\n"; return 0;
}

在这里插入图片描述

3. 定义一个点类(Point)、矩形类(Rectangle和立方体类(Cube)的层次结构。矩形包括长度和宽度两个新数据成员,矩形的位置从点类继承。立方体类由长度、宽度和高度构成要求各类提供支持初始化的构造函数和显示自己成员的成员函数。编写主函数,测试这个层次结构,输出立方体类的相关信息。

#include<iostream>
using namespace std;
class Point//描述二维平面中一个点的类
{double x, y;
public:Point(float i=0, float j=0) { x=i; y=j;}double area( ) { return 0.0;}
};
class Rectangle:public Point
{float length;protected:float width;public:Rectangle(){length=0;width=0;} Rectangle(float l,float w){length=l;width=w;}float Area(){return length*width;}float GetL(){return length;}float GetW(){return width;}void RPrint(){cout<<"矩形的长为:"<<length;cout<<"\t宽为"<<width;}
};
class Cuboid:public Rectangle
{float high;public:Cuboid(){high=0;}Cuboid(float l,float w,float h):Rectangle(l,w){high=h;} void CPrint(){cout<<"长方体的长为:"<<GetL()<<"\t宽为:"<<width;cout<<"\t高为:"<<high<<"\t体积为:"<<high*Area()<<'\n';}
};
int main(){Rectangle r(10,5);r.RPrint();cout<<"\t面积为:"<<r.Area()<<'\n';Cuboid c(6,3,10);cout<<"矩形的长为:"<<c.GetL()<<"\t宽为:"<<c.GetW();cout<<"\t面积为:"<<c.Area()<<'\n';c.CPrint(); 
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/228832.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络(1)

计算机网络&#xff08;1&#xff09; 小程一言专栏链接: [link](http://t.csdnimg.cn/ZUTXU) 计算机网络和因特网&#xff08;1&#xff09;因特网概念解读服务常见的服务 协议网络边缘特点强调 网络核心特点强调 小程一言 我的计算机网络专栏&#xff0c;是自己在计算机网络…

常用环境部署(十三)——GitLab整体备份及迁移

一、GitLab备份 注意&#xff1a;由于我的GitLab是docker安装的&#xff0c;所以我的操作都是在容器内操作的&#xff0c;大家如果不是用docker安装的则直接执行命令就行。 1、Docker安装GitLab 链接&#xff1a;常用环境部署(八)——Docker安装GitLab-CSDN博客 2、GitLab备…

【LMM 005】LLaVA-Interactive:集图像聊天,分割,生成和编辑三种多模态技能于一体的Demo

论文标题&#xff1a;LLaVA-Interactive: An All-in-One Demo for Image Chat, Segmentation, Generation and Editing 论文作者&#xff1a;Wei-Ge Chen, Irina Spiridonova, Jianwei Yang, Jianfeng Gao, Chunyuan Li 作者单位&#xff1a;Microsoft Research, Redmond 论文原…

Spring04

一、AOP的概念 AOP 为 (Aspect Oriented Programming) 的缩写&#xff0c;意为&#xff1a;面向切面编程&#xff0c;底层是使用动态代理的技术实现对目标方法的增强和控制访问等功能。 其中AOP中有几个重要的概念: 1、通知:增强的逻辑&#xff0c;或者后期要加入的代码。 2、目…

2024校招测试工程师笔试——经典错题记录和解析

大家好&#xff0c;这篇文章记录几个测开方向经典的例题&#xff0c;并给出相应解析&#xff0c;欢迎给出你的看法 下列关于软件性能测试的说法中&#xff0c;正确的是&#xff1a;&#xff08; &#xff09; A 性能测试的目的不是为了发现软件缺陷 B 压力测试与负载测试的目的…

【并发设计模式】聊聊Thread-Per-Message与Worker-Thread模式

在并发编程中&#xff0c;核心就是同步、互斥、分工。 同步是多个线程之间按照一定的顺序进行执行&#xff0c;比如A执行完&#xff0c;B在执行。而互斥是多个线程之间对于共享资源的互斥。两个侧重点不一样&#xff0c;同步关注的是执行顺序&#xff0c;互斥关注的是资源的排…

CGAL的空间排序

1、介绍 许多在CGAL中实现的几何算法都是增量的&#xff0c;因此它们的速度取决于插入顺序。此软件包提供了排序算法&#xff0c;可以大大提高此类算法的运行时间。 其基本原理是沿着空间填充曲线对对象进行排序&#xff0c;这样在插入顺序上&#xff0c;几何上接近的两个对象将…

.net8 AOT编绎-跨平台调用C#类库的新方法-函数导出

VB.NET AOT无法编绎DLL,微软的无能&#xff0c;正是你的机会 .net8 AOT编绎-跨平台调用C#类库的新方法-函数导出 1&#xff0c;C#命令行创建工程&#xff1a;dotnet new classlib -o CSharpDllExport 2&#xff0c;编写一个静态方法&#xff0c;并且为它打上UnmanagedCallersO…

Linux - 设置虚拟机和主机IP在同一网段(桥接)

1.查看主机ip地址等相关信息。 ipconfig -all 2.设置虚拟网络编辑器 打开虚拟网络编辑器 设置虚拟网络编辑器&#xff0c;设置为桥接模式。&#xff08;记得以管理员方式打开VMware&#xff09;。 3.修改虚拟机网卡文件 查看虚拟机ip,我们的目标是将其修改为与主机同一网段…

postman使用-04响应

文章目录 响应响应界面说明Pretty&#xff1a;格式化显示&#xff0c;以便查看Raw&#xff1a;不进行任何处理&#xff0c;显示响应数据的原始格式Preview&#xff1a;预览响应体&#xff0c;会自动换行&#xff0c;不会格式化&#xff08;有时候是数据&#xff0c;有时候是页面…

什么是缓存、为什么要用缓存、缓存分类、缓存测试、缓存更新、缓存设计考虑点、缓存测试点

一、缓存 缓存是一种将数据存储在高速缓存中的技术&#xff0c;它可以提高应用程序的性能和响应速度。 二、 为什么要用缓存 1. 高性能(主要目的) 查询耗时&#xff0c;但变化少&#xff0c;又有很多读请求情况下&#xff0c;可以将查询结果放到缓存中。减少对数据库的压力&…

Java位运算及移位运算

java中能表示整数数据类型的有byte、short、char、int、long&#xff0c;在计算机中占用的空间使用字节描述&#xff0c;1个字节使用8位二进制表示。 数据类型字节数二进制位数表示范围默认值byte18-27 – 27-10char2160 – 216-1\u0000 (代表字符为空 转成int就是0)short216-…

Word 将页面方向更改为横向或纵向

文章目录 更改整个文档的方向更改部分页面的方向方法1&#xff1a;方法2&#xff1a; 参考链接 更改整个文档的方向 选择“布局”>“方向”&#xff0c;选择“纵向”或“横向”。 更改部分页面的方向 需要达到下图结果&#xff1a; 方法1&#xff1a; 选:中你要在横向页面…

帆软报表中定时调度中的最后一步如何增加新的处理方式

在定时调度中,到调度执行完之后,我们可能想做一些别的事情,当自带的处理方式不满足时,可以自定义自己的处理方式。 产品的处理方式一共有如下这些类型: 我们想在除了上面的处理方式之外增加自己的处理方式应该怎么做呢? 先看下效果: 涉及到两方面的改造,前端与后端。…

C++日期类的实现

前言&#xff1a;在类和对象比较熟悉的情况下&#xff0c;我们我们就可以开始制作日期表了&#xff0c;实现日期类所包含的知识点有构造函数&#xff0c;析构函数&#xff0c;函数重载&#xff0c;拷贝构造函数&#xff0c;运算符重载&#xff0c;const成员函数 1.日期类的加减…

【产品设计】信息建设三驾马车:PLM系统拆解

本篇文章将介绍PLM的基础信息、发展及模块功能等内容&#xff0c;让大家对PLM有一个全面、完整地了解&#xff0c;方便在后期的工作中能快速地使用其解决方案&#xff0c;希望本篇文章能对你有所帮助。 PLM系统主要实现产品模块业务&#xff0c;既包含产品的创意设计、样品打样…

【源码】-MyBatis-如何系统地看源码

写在前面 前段时间做过一个项目&#xff0c;期间用到了动态数据源dynamic-datasource&#xff0c;经历了dbcp2的数据库连接池没有生效到排查定位、MyBatis多种数据库产品兼容、手写MyBatis拦截器等事情。 花费了好久&#xff0c;一直在打磨这篇文章&#xff08;不知道花费这么长…

thinkphp6.0升级到8.0

目录 一&#xff1a;升级过程 二&#xff1a;报错处理 最近写的项目需要使用thinkphp8.0&#xff0c;之前的老项目需要从php6.0升级到8.0&#xff0c;特此记录下升级过程。 一&#xff1a;升级过程 查看版本&#xff1a; php think version,我目前的版本是6.1.4 生成thin…

WPF+Halcon 培训项目实战(8-9):WPF+Halcon初次开发

文章目录 前言相关链接项目专栏运行环境匹配图片WPF Halcon组件HSmartWindowControlWPF绑定读取图片运行代码运行结果 抖动问题解决运行结果 绘制矩形绘制图像会消失 绘制对象绑定事件拖动事件 前言 为了更好地去学习WPFHalcon&#xff0c;我决定去报个班学一下。原因无非是想…

C/C++面向对象(OOP)编程-回调函数详解(回调函数、C/C++异步回调、函数指针)

本文主要介绍回调函数的使用&#xff0c;包括函数指针、异步回调编程、主要通过详细的例子来指导在异步编程和事件编程中如何使用回调函数来实现。 &#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &#x1f4cb;个人专栏&#xff1a;C/C精进之路 &…