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

news2024/12/26 0:42:07

文章目录

  • 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 std

class 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=0

A.change();//调用charge(),子类没有,去父类调用,x++,i++ 此时A的x=1,i=1
A.modify();//直接调用子类的modify(),x++,此时A的x=2,i=1
A.display();//打印A的x  x=2

B.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.返回的对象赋值给temp
	return 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.coloradmin.cn/o/1224455.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

安装银河麒麟linux系统docker(docker-compose)环境,注意事项(一定能解决,有环境资源)

1:安装docker环境必须使用麒麟的版本如下 2:使用docker-compse up -d启动容器遇到的文件 故障1:如果运行docker-compose up 报“Cannot create redo log files because data files are corrupt or the database was not shut down cleanly after creating the data files”…

webAPP基础学习

###视觉基础 part-I ####1.面试中常见的像素问题 >什么是像素? *1.什么是px? px-虚拟像素,css像素的单位 px是一个相对单位,相对于设备像素而言 >相对性 a.相对于同一个设备,css像素的可变的 css像素物理像素>会受到缩放的影响 css像素缩放倍数*单个物理像…

我认为除了HelloWorld之外,Python的三大数据转换实例可以作为开始学习Python的入门语言。

Python的三大数据转换实例 一、反转三位数 class Solution:def funtcion(self,number):hint(number/100)tint(number%100/10)zint(number%10)return 100*z10*th if __name____main__:solution Solution()num123new_num solution.funtcion(num)print("输入:{}".fo…

量化交易:传统小市值策略 VS AI市值策略

在BigQuant平台上可以快速开发股票传统策略和股票AI策略&#xff0c;今天拿市值因子来练手&#xff0c;看看两个策略在2015-01-01到2016-12-31这两年时间各自的收益风险情形。 市值因子是国内股票市场能够带来超额收益的alpha因子&#xff0c;已经被验证为长期有效的因子&…

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

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

11 月 11 日 ROS 学习笔记——ROS 架构及概念

文章目录 前言一、 ROS 文件系统级1). 工作空间 Ws2). 功能包3). 消息 msg4). 服务 srv 二、计算图级1). 动态加载节点 nodelet2). 主题 topic3). 服务 srv4). 消息 msg5). 试用练习5). 创建工作空间6). 创建 ROS 功能包和元功能包7). 编译ROS功能包8). 使用 ROS 节点9). 使用主…

实战提升(六)

前言&#xff1a;Practice makes perfect&#xff01;今天实战Leetcode链表分割还有回文结构。今天的题全都来自于牛客网。 实战一&#xff1a; 思路&#xff1a;我们一这个链表为例&#xff0c;小于5的链表尾插到第一个链表&#xff0c;大于5的链表尾插到第二个链表&#xf…

性能测试常见问题总结

01 硬件上的性能瓶颈 指的是CPU、内存、I/O读写速率&#xff0c;磁盘空间方面的问题。 02 网络上的性能瓶颈 指的网络带宽&#xff0c;网络波动&#xff0c;延时&#xff0c;丢包等。 03 应用程序上的性能瓶颈 指的是开发人员新开发出来的应用程序。 04 数据库的性能瓶颈…

如何实现一个下班倒计时程序

shigen日更文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 Hello伙伴们&#xff0c;好几天不见啦。最近也是晚上打球太累&#xff0c;加上一直在研究mybatis的多租户问题&…

风光能互补发电庭院路灯系统技术原理

风光互补发电系统是由风力发电机组配合太阳能电池组件组成&#xff0c;通过专用的控制逆变器&#xff0c;将风力发电机输出的低压交流电整流成直流电&#xff0c;并与光伏电池组件输出的直流电汇集在一起&#xff0c;充入蓄电池组&#xff0c;实现稳压、蓄能和逆变全过程&#…

Web前端—移动Web第二天(空间转换、动画、综合案例:全名出游)

版本说明 当前版本号[20231118]。 版本修改说明20231118初版 目录 文章目录 版本说明目录移动 Web 第二天01-空间转换空间转换简介平移视距旋转左手法则rotate3d-了解立体呈现案例-3d导航缩放 02-动画动画实现步骤animation复合属性animation拆分写法案例-走马灯精灵动画多组…

K-Means算法进行分类

已知数据集D中有9个数据点&#xff0c;分别是&#xff08;1,2&#xff09;&#xff0c;(2,3), (2,1), (3,1),(2,4),(3,5),(4,3),(1,5),(4,2)。采用K-Means算法进行聚类&#xff0c;k2&#xff0c;设初始中心点为&#xff08;1.1,2.2&#xff09;&#xff0c;&#xff08;2.3,3.…

k8s上Pod生命周期、重启策略、容器探测简介

目录 一.Pod的创建过程 二.Pod的终止过程 三.Pod的重启策略&#xff08;restartPolicy&#xff09; 1.Always 2.OnFailture 3.Never 4.示例 四.Pod生命周期内的5种状态&#xff08;相位&#xff09; 1.Pending 2.Running 3.Succeeded 4.Failed 5.Unknown 五.初始…

号卡分销管理系统搭建

随着移动互联网的发展&#xff0c;各种手机应用层出不穷&#xff0c;其中包括了很多用于企业管理的软件。号卡系统分销管理软件就是其中的一种。它是一种基于移动互联网的企业管理软件&#xff0c;能够帮助企业进行号卡的分销管理&#xff0c;从而提高企业的效率和竞争力。 …

OpenAI发布会中不起眼的重大更新

上周&#xff0c;OpenAI的历史首届开发者大会上&#xff0c;OpenAI的首席执行官山姆奥特曼展示了一系列产品更新&#xff0c;包含了众多重磅功能&#xff0c;就算单独拿出来都能让科技圈震一震&#xff0c;一下能发布这么多也真是家底厚。 果不其然&#xff0c;接下来的一周&am…

C#实现观察者模式

观察者模式是一种软件设计模式&#xff0c;当一个对象的状态发生变化时&#xff0c;其所有依赖者都会自动得到通知。 观察者模式也被称为“发布-订阅”模式&#xff0c;它定义了对象之间的一对多的依赖性&#xff0c;当一个对象状态改变时&#xff0c;所有依赖于它的对象都会得…

Unity 6 是下一个 LTS 版本即将发布

Unity 公司宣布&#xff0c;即将发布 Unity 6&#xff0c;并表示其为下一个长期支持版本 (LTS)。 Unity 在大会上演示了全新的 Unity 6引擎&#xff0c;并通过 Syncy Studios 采用 Unity 6 制作的《幻想王国&#xff08;Fantasy Kingdom&#xff09;》Demo 进行了演示&#xff…

C#单例模式懒汉式与饿汉式

单例模式一般分为懒汉模式和饿汉模式&#xff0c;懒汉式单例在第一次引用时创建实例&#xff0c;不是在类加载时&#xff1b;饿汉式单例模式是一种在类加载时就创建实例的方式&#xff0c;因此也称为静态初始化。 单例模式实现的技巧时构造私有&#xff0c;向外提供静态实例。…

键鼠自动化2.0展示

软件介绍&#xff1a;桌面键鼠自动化工具 Qtc 编写&#xff1a; 本软件采用Qt C编写&#xff0c;旨在提供高效、跨平台的桌面键鼠自动化解决方案。Qt C框架的选择确保了软件的稳定性、可靠性&#xff0c;并通过其图形用户界面实现了用户友好的操作体验。 鼠标移动与点击&#…

目标检测—YOLO系列(二 ) 全面解读复现YOLOv1 PyTorch

精读论文 前言 从这篇开始&#xff0c;我们将进入YOLO的学习。YOLO是目前比较流行的目标检测算法&#xff0c;速度快且结构简单&#xff0c;其他的目标检测算法如RCNN系列&#xff0c;以后有时间的话再介绍。 本文主要介绍的是YOLOV1&#xff0c;这是由以Joseph Redmon为首的…