【C/C++笔试练习】继承和派生的概念、虚函数的概念、派生类的析构函数、纯虚函数的概念、动态编译、多态的实现、参数解析、跳石板

文章目录

  • C/C++笔试练习
  • 选择部分
    • (1)继承和派生的概念
    • (2)程序分析
    • (3)虚函数的概念
    • (4)派生类的析构函数
    • (5)纯虚函数的概念
    • (6)动态编译
    • (7)子类的析构函数
    • (8)多态的实现
    • (9)程序分析
    • (10)程序分析
  • 编程题 day13
    • 参数解析
    • 跳石板

C/C++笔试练习

选择部分

(1)继承和派生的概念

  下面叙述不正确的是()

  A. 派生类一般都用公有派生
  B. 对基类成员的访问必须是无二义性的
  C. 赋值兼容规则也适用于多重继承的组合
  D. 父类的公有成员在派生类中仍然是公有的

  答案:D

  在面向对象编程中,派生类是通过从一个或多个基类派生而来的。这里有几个关键概念和规则:

  派生方式:派生类可以从基类以公有(public)、保护(protected)或私有(private)的方式派生。这意味着基类的公有成员在派生类中仍然是公有的,保护成员在派生类中是保护的,私有成员在派生类中是不可访问的。

  考虑到这个规则,对于选项D,父类的公有成员在派生类中仍然是公有的,这个叙述是不正确的。应该是“父类的公有成员在派生类中仍然是公有的,而保护成员和私有成员不可访问”。

  访问基类成员:在派生类中访问基类的公有成员时,访问必须是明确且无二义性的。 这意味着如果基类有多个同名成员,那么在派生类中访问时必须明确指定是哪个基类的成员。所以选项B的叙述是正确的。

  赋值兼容规则:在多重继承的情况下,赋值兼容规则也适用。这意味着基类的类型可以被看作是派生类的类型。因此选项C的叙述是正确的。

  赋值兼容规则适用于多重继承:

class Base {};class D: public Base
{};int main()
{Base b;D d;
}

  (1)b=d; 子类对象可以复制父类无需转化。

  (2)Base* pd=&d; 子类对象地址可以直接赋给父类指针。

  (3)Base& rb=d; 可以使用子类对象对父类引用初始化,父类的公有成员在派生类仍为公有(前提是不是私有继承)。

  通常我们使用公有派生来创建派生类,因为这样可以使派生类具有和基类相同的接口,从而可以替换基类。 所以选项A的叙述是正确的。

  

(2)程序分析

  下面 C++ 程序的运行结果是()

#include <iostream>
using namespace stdclass parent {int i;
protected:int x;
public:parent() { x = 0; i = 0; }void change() { x++; i++; }void display();
};class son :public parent {
public:void modify();
};void parent::display() {cout << "x=" << x << endl;
}void son::modify() {x++;
}int main() {son A;parent B;A.display();A.change();A.modify();A.display();B.change();B.display();return 0;
}

  A.x=1 x=0 x=2
  B.x=2 x=0 x=1
  C.x=0 x=2 x=1
  D.x=0 x=1 x=2

  答案:C

son A;//创建子类A,先调用父类构造函数parent(),x=0,y=0,再调用子类构造函数,这里系统默认生成了一个
parent B;//创建父类B,直接调用构造函数parent(),x=0,y=0
A.display();//打印A的x  x=0A.change();//调用charge(),子类没有,去父类调用,x++,i++ 此时A的x=1,i=1
A.modify();//直接调用子类的modify(),x++,此时A的x=2,i=1
A.display();//打印A的x  x=2B.change();//直接调用父类的charge(),x++,i++, 此时B的x=1,i=1
B.display();//这里打印B中的成员变量x  x=1  故答案为 0 2 1 

在这里插入图片描述

  

(3)虚函数的概念

  关于虚函数的描述正确的是()

  A. 派生类的虚函数与基类的虚函数具有不同的参数个数和类型
  B. 内联函数不能是虚函数
  C. 派生类必须重新定义基类的虚函数
  D. 虚函数可以是一个static型的函数

  答案:B

  A选项提到派生类的虚函数与基类的虚函数可以有不同的参数个数和类型。这是不正确的。如果只看这个语义,派生类的虚函数与基类的虚函数没有什么关系。即使指的是相同的虚函数,那其中的参数列表(包括个数和类型)也必须是一样的。

  B选项说内联函数不能是虚函数。这是正确的。内联函数会展开,但是在虚标中存放的是函数地址,如果内联函数根据地址展开,就无法找到函数地址。所以内联函数不能是虚函数。

  C选项说派生类必须重新定义基类的虚函数。这是不正确的。如果基类的虚函数是纯虚函数(即没有实现),那么任何派生类都必须提供这个函数的实现。但如果基类的虚函数有实现,那么派生类可以选择是否重新定义这个函数。

  D选项说虚函数可以是一个static型的函数。这也是不正确的。虚函数需要this指针调用对象,调用虚表,而静态成员函数中没有this指针,所以不能被声明为虚函数。

  

(4)派生类的析构函数

  当一个类对象的生命周期结束后,关于调用析构函数的描述正确的是()

  A. 如果派生类没有定义析构函数,则只调用基类的析构函数
  B. 如果基类没有定义析构函数,则只调用派生类的析构函数
  C. 先调用派生类的析构函数,后调用基类的析构函数
  D. 先调用基类的析构函数,后调用派生类的析构函数

  答案:C

  在C++中,当一个对象被销毁时,其析构函数会被首先调用。如果这个对象是由一个派生类(子类)对象实例化的(前提是它的的析构函数是形成了多态),那么派生类的析构函数将首先被调用,然后是基类的析构函数。

  这个规则确保了派生类在基类之前释放任何由派生类管理的资源,以防止资源泄漏。 如果派生类没有定义析构函数,那么编译器会自动生成一个析构函数,这个析构函数只会调用基类的析构函数。如果基类也没有定义析构函数,那么编译器会为基类生成一个默认的析构函数。

  

(5)纯虚函数的概念

  以下关于纯虚函数的说法,正确的是()

  A. 声明纯虚函数的类不能实例化
  B. 声明纯虚函数的类成虚基类
  C. 子类必须实现基类的纯虚函数
  D. 纯虚函数必须是空函数

  答案:A

  A. 声明纯虚函数的类不能实例化 - 这是正确的。当一个类包含一个或多个纯虚函数时,它被称为抽象类。抽象类不能被实例化,只能被其他类继承。

  纯虚函数的定义:

virtual void fun()=0;

  B. 声明纯虚函数的类成虚基类 - 这是不正确的。虚函数和虚基类完全是两个概念,一个类包含纯虚函数并不影响它作为基类的类型。 只有当一个类作为虚基类使用时,它才需要至少一个纯虚函数。虚基类一般用于解决菱形继承。

  C. 子类必须实现基类的 - 这是不正确的。如果一个子类继承自一个包含纯虚函数的基类,那么子类不一定实现这些纯虚函数。多态实现,否则不实现。

  D. 纯虚函数必须是空函数 - 这是不正确的。纯虚函数只是声明,没有提供实现。它们在基类中的存在是为了让派生类实现它们。纯虚函数可以是任何类型的函数,包括带有实现的非空函数。

  

(6)动态编译

  下列描述,正确的一共有多少个()

  1)const char *p,这是一个常量指针,p的值不可修改
  2)在64位机上,char *p= “abcdefghijk”; sizeof( p )大小为12
  3)inline会检查函数参数,所以调用开销显著大于宏
  4)重载是编译时确定的,虚函数是运行时绑定的

  A. 1
  B. 2
  C. 3
  D. 4

  答案:A

  const char *p这是一个常量指针,p的值可以修改:const char *p是一个 指向常量的指针,这意味着你不能通过这个指针来改变它所指向的值,但你可以改变这个指针本身所指向的地址。

  在64位机上,char *p= “abcdefghijk”; sizeof( p )大小为12:这个描述是错误的。在64位机器上,一个指针的大小通常是8字节。所以sizeof(p)应该返回8,而不是12。

  inline会检查函数参数,所以调用开销显著大于宏:这个描述也是错误的。内联函数的主要目的是减少函数调用的开销,因为它可以避免进行一次函数调用的额外开销。但其实开销和宏也差不多,提不上显著的说法。

  重载是编译时确定的,虚函数是运行时绑定的:这个描述是正确的。重载是在编译时确定的(静态编译),编译器会根据函数名和参数类型在编译时确定调用哪个函数。而虚函数是在运行时动态绑定的(动态编译),编译器会生成一个虚函数表(vtable),并在运行时根据对象的实际类型来选择调用哪个虚函数的实现。

  

(7)子类的析构函数

  C++将父类的析构函数定义为虚函数,下列正确的是哪个()

  A. 释放父类指针时能正确释放子类对象
  B. 释放子类指针时能正确释放父类对象
  C. 这样做是错误的
  D. 以上全错

  答案:A

  在C++中,如果一个父类的析构函数被定义为虚函数,那么当通过父类指针释放一个子类对象时,能正确释放子类对象。这是因为虚析构函数的目的是为了在释放对象时正确地调用子类的析构函数。

  然而,如果子类的析构函数没有定义为虚函数,那么通过父类指针释放子类对象时,可能会导致子类的析构函数不被调用,从而造成资源泄漏。

  

(8)多态的实现

  下列关于多态性说法不正确的是()

  A. 多态性是指同名函数对应多种不同的实现
  B. 重载方式仅有函数重载
  C. 重载方式包含函数重载和运算符重载
  D. 多态性表现为静态和动态两种方式

  答案:B

  多态性是指同名函数对应多种不同的实现, 所以选项A是正确的。

  多态性有两种表现形式:编译时的多态性(静态)和运行时的多态性(动态)。编译时的多态性可以通过函数重载和运算符重载实现,所以选项C是正确的。运行时的多态性可以通过虚函数实现,所以选项D也是正确的。

  重载方式不只有函数重载,还包括运算符重载,所以选项B是不正确的。

  

(9)程序分析

  分析一下这段程序的输出

#include<iostream>
using namespace std;
class B
{
public:B(){cout << "default constructor" << " ";}~B(){cout << "destructed" << " ";}B(int i): data(i){cout << "constructed by parameter" << data << " ";}
private: int data;
};B Play( B b)
{return b;
}int main(int argc, char *argv[])
{B temp = Play(5);return 0;
}

A. constructed by parameter5 destructed destructed
B. constructed by parameter5 destructed
C. default constructor" constructed by parameter5 destructed
D. default constructor" constructed by parameter5 destructed destructed

  答案:A

class B
{
public:B(){cout << "default constructor" << " ";}~B()//6.最后调用析构函数,打印destructed{cout << "destructed" << " ";}B(int i) : data(i)//3.自动调用单参数构造函数,i=5,打印constructed by parameter5{cout << "constructed by parameter" << data << " ";}
private: int data;
};B Play(B b)//2.将5作为参数给B的构造函数  4.返回构造好的B对象,结束要调用一次析构, 打印destructed
{return b;
}int main(int argc, char* argv[])
{B temp = Play(5);//1.先调用Play()函数  5.返回的对象赋值给tempreturn 0;
}

在这里插入图片描述

  

(10)程序分析

  求输出结果

#include <iostream>
using namespace std;
class A
{
public:virtual void print(){cout << "A::print()" << "\n";}
};class B: public A
{public: 
virtual void print(){cout << "B::print()" << "\n";}
};class C: public A
{public: virtual void print(){cout << "C::print()" << "\n";}
};void print(A a)
{a.print();
}int main()
{A a, *aa, *ab, *ac;B b;C c;aa = &a;ab = &b;ac = &c;a.print();b.print();c.print();aa->print();ab->print();ac->print();print(a);print(b);print(c);
}

A. C::print() B::print() A::print() A::print() B::print() C::print() A::print() A::print() A::print()
B. A::print() B::print() C::print() A::print() B::print() C::print() A::print() A::print() A::print()
C. A::print() B::print() C::print() A::print() B::print() C::print() B::print() B::print() B::print()
D. C::print() B::print() A::print() A::print() B::print() C::print() C::print() C::print() C::print()

  答案:B

A a, * aa, * ab, * ac;//创建A对象a,和A类型指针aa,ab,ac 
B b;//实例化B对象b
C c;//实例化C对象c
aa = &a;//父类指针指向父类 A->A
ab = &b;//父类指针指向子类 A->B
ac = &c;//父类指针指向子类 A->C
//静态编译
a.print();//A对象直接调用A中成员函数print()  打印A::print()
b.print();//B对象直接调用B中成员函数print()  打印B::print()
c.print();//C对象直接调用C中成员函数print()  打印C::print()
//多态
aa->print();//父类对象直接调用父类函数print() 打印A::print()
ab->print();//父类指针A指向子类对象B,且为虚函数,实现多态  打印B::print()
ac->print();//父类指针A指向子类对象C,且为虚函数,实现多态  打印C::print()
//永远调用的是父类的函数
print(a);//父类对象A转入父类对象A  打印A::print()
print(b);//子类对象B传入父类对象A  打印A::print()
print(c);//子类对象C传入父类对象A  打印A::print()

在这里插入图片描述

            

编程题 day13

参数解析

参数解析

  本题通过以空格和双引号为间隔,统计参数个数。对于双引号,通过添加flag,保证双引号中的空格被输出。

#include<iostream>
#include<string>
#include<vector>
using namespace std;void cmdLineParse(const string& str) 
{string tmp = "";vector<string> svec;bool flag = false; //用于判断是否处于字符串的状态for (int i = 0; i < str.size(); ++i) {if (str[i] == '"') { //判断是否是字符串的起始或者结束flag = !flag; //说明处于了字符串的状态} else if (str[i] == ' ' &&!flag) { //判断参数的分隔或者是否为字符串的内容svec.push_back(tmp);tmp = "";} else { //正常的参数内容tmp += str[i]; //xcopy}}//追加最后一个参数svec.push_back(tmp); cout << svec.size() << endl;for (int i = 0; i < svec.size(); ++i)cout << svec[i] << endl;
}int main() 
{string str;while (getline(cin, str)) {cmdLineParse(str);}return 0;
}

  

跳石板

跳石板

  将1 - M个石板看做一个结果数组stepNum,每个stepNum[i]储存着从起点到这一步最小的步数,其中0为不能到达。 从起点开始对stepNum进行遍历,先求i的所有约数(即从stepNum[i]能走的步数),然后更新那几个能到达的位置的最小步数。如果不能到达则更新为此时位置的最小步数 + 1,如果是能到达的就更新为min(已记录的最小步数,此处的最小步数 + 1)),遍历一遍后得到结果。

#include<iostream>
#include<vector>
#include<limits.h>
#include<math.h>
using namespace std;void get_div_num(int v, vector<int>& a) 
{for (int i = 2; i <= sqrt(v); ++i){if (v % i == 0) {a.push_back(i);if (v / i != i)a.push_back(v / i);}}
}int Jump(int n, int m) 
{vector<int> step(m + 1, INT_MAX); //int_max表示不可达到step[n] = 0; //当前位置初始化for (int i = n; i < m; ++i){if (step[i] == INT_MAX)continue;vector<int> a;//获取i的约数,并保存get_div_num(i, a);for (int j = 0; j < a.size(); ++j){if (a[j] + i <= m && step[a[j] + i] != INT_MAX) {//需要挑选一个最小值step[a[j] + i] = step[a[j] + i] < step[i] + 1 ? step[a[j] + i] : step[i] + 1;} else if (a[j] + i <= m) {step[a[j] + i] = step[i] + 1;}}}return step[m] == INT_MAX ? -1 : step[m];
}int main()
{int n, m, min_step;while (cin >> n >> m) {min_step = Jump(n, m);cout << min_step << endl;}return 0;
}

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

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

相关文章

Filter和ThreadLocal结合存储用户id信息

ThreadLocal并不是一个Thread&#xff0c;而是Thread的局部变量。当使用ThreadLocal维护变量时&#xff0c;ThreadLocal为每个使用该变量的线程提供独立的变量副本&#xff0c;所以每一个线程都可以独立地改变自己的副本&#xff0c;而不会影响其它线程所对应的副本。ThreadLoc…

Windows10下Tomcat8.5安装教程

文章目录 1.首先查看是否安装JDK。2.下载3.解压到指定目录&#xff08;安装路径&#xff09;4.启动Tomcat5.常见问题5.1.如果出现报错或者一闪而过5.2.Tomcat乱码 1.首先查看是否安装JDK。 CMD窗口输入命令 java -version 2.下载 历史版本下载地址&#xff1a;https://archi…

JDBC,Java连接数据库

下载 JDBC https://mvnrepository.com/ 创建项目&#xff0c;然后创建一个目录并将下载好的 jar 包拷贝进去 选择 Add as Library&#xff0c;让这个目录能被项目识别 连接数据库服务器 在 JDBC 里面&#xff0c;使用 DataSource 类来描述数据库的位置 import com.mysql.cj.…

Lstm+transformer的刀具磨损预测

视频讲解: 基于Lstm+transformer的刀具磨损预测实战_哔哩哔哩_bilibili 结果展示: 数据展示: 主要代码: # pip install openpyxl -i https://pypi.tuna.tsinghua.edu.cn/simple/ # pip install optuna -i https://pypi.tuna.tsinghua.edu.cn/simple/ import numpy as np…

OpenCV C++ 图像 批处理 (批量调整尺寸、批量重命名)

文章目录 图像 批处理(调整尺寸、重命名)图像 批处理(调整尺寸、重命名) 拿着棋盘格,对着相机变换不同的方角度,采集十张以上(以10~20张为宜);或者棋盘格放到桌上,拿着相机从不同角度一通拍摄。 以棋盘格,第一个内焦点为坐标原点,便于计算世界坐标系下三维坐标; …

国内优质企业网盘推荐:满足您的文件存储与共享需求

企业网盘是主要用于企业工作过程中给的文件存储、共享以及协作。很多用户在挑选文件协作工具时更偏爱国内的工具&#xff0c;原因是使用上可能更贴合国人的使用习惯&#xff01; 那么现在国内做的比较好的企业网盘有什么&#xff1f; Zoho Workdrive企业网盘&#xff0c;ZOHO…

linux配置固定ip(两种方法)

首先刚下载的vm&#xff0c;刚创建的虚拟机&#xff0c;肯定是需要配置ip的 其次以前我的每次都是设置自动ip&#xff0c;这样每次登录都会自动获取ip地址&#xff0c;并且每次的ip都不相同。 ~方法&#xff1a; 开机登陆后 1)Cd /etc/sysconfig/network-scripts 2)Vi ifcf…

通过 Canal 将 MySQL 数据实时同步到 Easysearch

Canal 是阿里巴巴集团提供的一个开源产品&#xff0c;能够通过解析数据库的增量日志&#xff0c;提供增量数据的订阅和消费功能。使用 Canal 模拟成 MySQL 的 Slave&#xff0c;实时接收 MySQL 的增量数据 binlog&#xff0c;然后通过 RESTful API 将数据写入到 Easysearch 中。…

Django的可重用HTML模板示例

01-配置并运行Django项目 首先按照博文 https://blog.csdn.net/wenhao_ir/article/details/131166889配置并运行Django项目。 02-创建可重用模板文件 templates目录下新建目录common&#xff0c;然后在目录common下新建文件&#xff1a;navbar.html&#xff0c;并写入下面的…

mac无法向移动硬盘拷贝文件怎么解决?不能读取移动硬盘文件怎么解决

有时候我们在使用mac的时候&#xff0c;会遇到一些问题&#xff0c;比如无法向移动硬盘拷贝文件或者不能读取移动硬盘文件。这些问题会给我们的工作和生活带来不便&#xff0c;所以我们需要找到原因和解决办法。本文将为你介绍mac无法向移动硬盘拷贝文件怎么回事&#xff0c;以…

Linux系统中sh脚本编写

文章目录 Linux系统中sh脚本编写1.在编写sh脚本前了解一下基本语法1.1 if语句单分支双分支多分枝 1.2 for语法 2. 自己写的demo &#xff1a;自动部署前端项目 &#xff08;自动拉取代码&#xff0c;打包&#xff0c;部署nginx&#xff09;3.定时执行 shell脚本 Linux系统中sh脚…

Go vs Rust:文件上传性能比较

在本文中&#xff0c;主要测试并比较了Go—Gin和Rust—Actix之间的多部分文件上传性能。 设置 所有测试都在配备16G内存的 MacBook Pro M1 上执行。 软件版本为&#xff1a; Go v1.20.5Rust v1.70.0 测试工具是一个基于 libcurl 并使用标准线程的自定义工具&#xff0c;能…