嵌入式软件工程师面试题——2025校招社招通用(五)

news2025/1/16 3:46:24

说明:

  • 面试题来源于网络书籍,公司题目以及博主原创或修改(题目大部分来源于各种公司);
  • 文中很多题目,或许大家直接编译器写完,1分钟就出结果了。但在这里博主希望每一个题目,大家都要经过认真思考,答案不重要,重要的是通过题目理解所考知识点,好应对题目更多的变化;
  • 博主与大家一起学习,一起刷题,共同进步;
  • 写文不易,麻烦给个三连!!!

1.编写类String的构造函数、析构函数和赋值函数

答案

#include <iostream>
using namespace std;


class String
{
public:
    // 普通构造函数
    String(const char *str = NULL);
    // 拷贝构造函数
    String(const String &other);
    // 析构函数
    ~String();
    // 赋值函数
    String& operator=(const String &other);
private:
    char *m_data;
};



int main()
{
    

    return 0;
}

1.String的析构函数
为了防止内存泄漏,我们还需要定义一个析构函数。当一个String对象超出它的作用域时,这个析构函数将会释放它所占用的内存。代码如下:

String::~String(void)
{
    delete [] m_data;
}

2.String的构造函数
这个构造函数可以帮助我们根据一个字符串常量创建一个MyString对象。这个构造函数首先分配了足量的内存,然后把这个字符串常量复制到这块内存,代码如下:

String::String(const char *str)
{
    if(str == NULL)
    {
        m_data = new char[1]; 
        *m_data = '\0';
    }
    else
    {
        int length = strlen(str);
        m_data = new char[length + 1];
        strcpy(m_data, str);
    }
}

3.String的拷贝构造函数
拷贝构造函数还可以帮助我们在函数调用中以传值方式传递一个Mystring参数,并且在当一个函数以值的形式返回Mystring对象时实现“返回时复制”。

String::String(const String &other)
{
    int length = strlen(other.m_data);
    m_data = new char[length+1];
    strcpy(m_data, other.m_data);
}

4.String的赋值函数

String &String::operator= (const String &other)
{
    if(this == &other)
        return *this;
    
    delete [] m_data;

    int length = strlen(other.m_data);
    m_data = new char[length+1];
    strcpy(m_data, other.m_data);

    return *this;
}

2.哪个子类的虚函数重新声明是正确的?

A.Base* Base::copy(Base*);
Base* Derived::copy(Derived*);
B.Base* Base::copy(Base*);
Derived* Derived::copy(Base*);
C.ostream& Base::print(int,ostream&=cout);
ostream& Derived::print(int,ostream&);
D.void Base::eval() const;
void Derived::eval();
解析
本题问的是哪个派生类的虚函数再声明是对的。
A是重载;B会导致编译错误;C是真正的多态;D是重载。

答案: C

3.什么是多态?

答案:
开门,开窗户,开电视。在这里的“开”就是多态!
多态性可以简单地概括为“一个接口,多种方法”,在程序运行的过程中才决定调用的函数。多态性是面向对象编程领域的核心概念。
多态(Polymorphisn),按字面的意思就是“多种形状”。多态性是允许你将父对象设置成为和它的一个或更多的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单地说就是一句话,允许将子类类型的指针赋值给父类类型的指针。多态性在Object Pascal和C++中都是通过虚函数(Virtual Function)实现的。

4.重载和覆盖有什么不同?

答案:
C++中的重载(Overloading)和覆盖(Overriding)是两个不同的概念,它们分别用于处理函数和方法的多态性。

重载是指在同一作用域内定义多个名称相同但参数类型或个数不同的函数。编译器会根据函数调用时传递的参数类型和个数来匹配合适的重载函数。重载函数具有相同的名称,但不同的签名,可以有不同的返回值类型,但不能只是返回类型不同而函数参数类型和个数相同。C++中支持运算符重载,允许自定义运算符的操作行为。
说法二:overload约定成俗地被翻译为“重载”,是指编写一个与已有函数同名但是参数表不同的函数。例如一个函数既可以接收整型数作为参数,也可以接收浮点数作为参数。重载不是一种面向对象的编程,而只是一种语法规则,重载与多态没有什么直接关系。

覆盖是指在派生类定义一个与基类相同函数名、参数列表和返回类型的函数,并使用override关键字显式地表示这个函数是对基类函数的覆盖。当通过基类指针或引用调用这个函数时,实际执行的是派生类的函数。覆盖的函数必须与基类函数在参数列表、返回类型和const属性上完全匹配,否则会出现编译错误。如果基类函数是虚函数,则覆盖的函数也必须是虚函数。
说法二:override(覆盖)是指派生类重写基类的虚函数,就像我们前面在B类中重写了A类中的foo()函数。重写的函数必须有一致的参数表和返回值(C++标准允许返回值不同的情况,但是很少有编译器支持这个特性)。Override这个单词好像一直没有什么合适的中文词汇来对应。有人译为“覆盖”,还贴切一些。

5.下面哪个不能在编译时间被解析?

A.Macros
B.Inline functions
C.Template in C++
D.virtual function calls in C++

答案:D

6.请描述模板类的友元重载,用C++代码实现

答案

#include <iostream>
using namespace std;

// 定义一个非模板函数,作为模板类的友元,并与模板类中的某个成员函数同名
template<typename T>
class MyClass {
private:
    T x;
public:
    MyClass(T a) : x(a) {}
    // 声明友元函数
    friend void func(MyClass obj);
};

// 定义友元函数,通过友元重载可以访问模板类中的私有成员x
void func(MyClass<int> obj) {
    cout << "x = " << obj.x << endl;
}

int main() {
    MyClass<int> obj(10);
    // 调用友元函数
    func(obj);
    return 0;
}

7.一个类有5个虚方法,下列说法正确的是哪项?

A. 类中的每个对象都有第一个虚方法的地址,每一个方法都有下一个虚方法的地址。
B. 类中的每个对象都有一个链表用来存虚方法地址。
C. 类中的每个对象都保存5个虚方法的地址。
D. 类中的每个对象有一个结构用来保存虚方法地址。

解析
在C++中,虚函数通过虚函数表(vtable)来实现。每个类只有一个虚函数表,其中保存了该类所有虚函数的地址。每个对象都有一个指向虚函数表的指针,这个指针被称为虚函数表指针(vptr)。当通过对象调用虚函数时,实际上是通过该对象的虚函数表指针来查找并调用相应的虚函数。
对于一个有5个虚函数的类,每个对象在内存中都会有一个虚函数表指针,并且这个虚函数表中包含了这个类的5个虚函数的地址。所以每个对象都保存了5个虚方法的地址。

选项A、B和D都不正确。类中的每个对象并不保存每个虚函数的地址,而是保存一个指向虚函数表的指针,并通过这个指针来访问虚函数表的地址。同时,虚函数表中的地址存储的是每个虚函数的地址,而不是下一个虚函数的地址。

答案: B

8.下面程序的结果是什么?

#include <iostream>
#include <memory.h>
#include <assert.h>
using namespace std;

class A{
    char k[3];
public:
    virtual void aa() {};
};

class B: public virtual A{
    char j[3];
public:
    virtual void bb() {};
};

class C: public virtual B {
    char i[3];
public:
    virtual void cc() {};
};

int main()
{
    cout << "sizeof(A): " << sizeof(A) << endl;
    cout << "sizeof(B): " << sizeof(B) << endl;
    cout << "sizeof(C): " << sizeof(C) << endl;

    return 0;
}

解析:

  • 对于class A,由于有一个虚函数,那么必须有一个对应的虚函数表来记录对应的函数入口地址。每个地址需标有一个虚指针,指针的大小为4。类中还有一个char k[3],每一个char值所占位置是1,所以char k[3]所占大小是3。做一次数据对齐后(编译器里一般以4的倍数为对齐单位),char k[3]所占大小变为4。sizeof(A)的结果就是char k[3]所占大小4和虚指针所占大小4,两者之和等于8。
  • 对于class B,由于class B虚继承了class A,同时还拥有自己的虚函数,那么class B中首先拥有一个vfptr_B,指向自己的虚函数表。还有char j[3],大小为4。可虚继承该如何实现?首先要通过加入一个虚类指针(记vbptr_B_A)来指向其父类,然后还要包含父类的所有内容。有些复杂,不过还不难想象。sizeof(B)的结果就是char k[3]所占大小4和虚指针vfptr_B所占大小4加sizeof(A)所占大小8,三者之和等于16。
  • 下面是class C了。class C首先也得有个vfptr_C,然后是char i[3],然后是sizeof(B),所以sizeof(C)的结果就是char i[3]所占大小4和虚指针vfptr_C所占大小4加sizeof(B)所占大小16,三者之和等于24。

在这里插入图片描述

答案: 8 16 24

9.说一下多重继承的优点和缺陷

答案:
多重继承是指一个类可以同时从多个基类派生而来。它具有以下优点和缺陷:
优点:

  1. 提供了更大的灵活性:多重继承使得一个类可以从多个基类中继承不同的特性和行为,从而提供更大的灵活性。这对于构建复杂的对象结构和实现多样化的功能非常有用。
  2. 实现代码重用:通过多重继承,可以将不同的基类中的公共代码和功能集成到一个派生类中,实现代码的重用。这样可以减少重复编写相似代码的工作量,提高代码的可维护性和复用性。
  3. 更好地模拟现实世界:在一些情况下,某个类可能具有多个角色或特性,而多重继承可以更好地模拟现实世界中的这种复杂关系。例如,一个类可以同时继承自动物和会飞行的特性,这样更贴近真实世界的设计。

缺陷:

  1. 命名冲突和二义性:由于多个基类可能具有相同的成员函数或数据成员,多重继承可能导致命名冲突和二义性。这就需要在派生类中进行解决,可能需要使用作用域解析运算符(::)来明确指定使用的成员。
  2. 复杂性增加:多重继承会增加程序的复杂性,因为需要考虑多个基类之间的关系和调用顺序。特别是在多层次或菱形继承中,派生类可能会继承相同的基类多次,产生冗余的数据副本和额外的开销。
  3. 设计和维护困难:多重继承可能导致设计和维护上的困难,因为需要考虑更多的关系和交互。同时,当基类发生改变时,派生类可能也需要进行相应的修改,增加了代码的脆弱性。

10.下面的程序有何错误?

#include <iostream>
using namespace std;

class Shape
{
public:
    Shape() {}
    ~Shape() {}
    virtual void Draw() = 0;
};

int main()
{
    Shape s1;

    return 0;
}

答案:
因为Shape类中的Draw函数是一个纯虚函数,所以Shape类是不能实例化一个对象的。Shape s1;是不可以的,解决方法是把Draw函数修改成一般的虚函数。

#include <iostream>
using namespace std;

class Shape
{
public:
    Shape() {}
    ~Shape() {}
    virtual void Draw();
};

int main()
{
    Shape s1;

    return 0;
}

11.什么是虚指针?

答案:
虚指针(vptr)是C++中用于实现多态性的一种机制。它是一个指向虚函数表的指针,每个对象都有自己的虚指针。
虚函数表是一个存储每个类的虚函数地址的表格,编译器在编译时会为每个类生成一个虚函数表。当类中有虚函数时,编译器会在类的布局中增加一个指向虚函数表的指针vptr,并将其作为类的首个成员变量。
当对象被创建时,虚指针vptr会被初始化指向该对象所属类的虚函数表。当通过指向基类的指针或引用调用虚函数时,程序会先根据对象的虚指针找到该对象所属的类的虚函数表,再根据虚函数表中相应的索引找到实际要调用的函数地址,最后进行函数调用。
使用虚指针和虚函数表可以实现动态绑定,即在运行时根据对象类型确定调用哪个函数,从而实现多态性。这也是C++中面向对象编程的一个重要特性。

12.求下列程序的输出结果

int main()
{
    printf("%f\n", 5);
    printf("%d\n", 5.01);

    return 0;
}

解析:

  • 第一个printf语句中,使用了%f格式说明符,但是传入的参数是整数5。因为%f用于输出浮点数,而不是整数,所以这会导致输出的结果可能是不确定的。在某些编译器中,可能会将整数解释为浮点数,输0.000000。但是这并不是一个可靠的行为。
  • 第二个printf语句中,使用了%d格式说明符,但是传入的参数是浮点数5.01。因为%d用于输出整数,而不是浮点数,所以这也会导致输出的结果不确定。

答案:第一个答案是0.000000。 第二个答案是一个大数。

13.关键字volatile有什么含意?并给出3个不同的例子

答案:
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:

  • 并行设备的硬件寄存器(如状态寄存器)。
  • 个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
  • 多线程应用中被几个任务共享的变量

14.关键字static的作用是什么?

答案:

  • 函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值。
  • 在模块内的static全局变量可以被模块内所有函数访问,但不能被模块外其他函数访问。
  • 在模块内的static函数只可被这一模块内的其他函数调用,这个函数的使用范围被限制在声明它的模块内。
  • 在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝。
  • 在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量。

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

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

相关文章

仿真翻页企业内刊制作方法

现如今很多企业都会把自身的企业文化做成电子内刊形式&#xff0c;不再停留于传统纸质的形式&#xff0c;而这种电子版的书更容易被翻阅和传播。特别是员工可以随时随地来阅读企业的文化价值和发展趋向&#xff0c;进而创造出更多的经济效益。不得不说&#xff0c;一本企业文化…

Vue3最佳实践 第八章 ESLint 与 测试 (TypeScript 中Jest与检测环境集成)

TypeScript 中Jest与检测环境集成 ​Vite 已经发布很久了现在Vue3和Vite的生态正在蓬勃发展&#xff0c;现在很多项目中都用到了Vite vue3TypeScript技术栈&#xff0c;进行企业级的项目开发。本文将一步步帮助你创建一个标准的Vite Vue3 TypeScriptJest企业级开发与测试环境…

wxpython如何设置window上任务栏的进度条

该功能是各大编译器或者一些软件在执行耗时操作时&#xff0c;显示进度的一种方式&#xff1a; Qt 如果是使用的pyQt或者是Qt就很简单了&#xff0c;直接使用QWinTaskbarProgress就可以完成该功能。 Wxpython 但是wxpython就没有那么简单了&#xff0c;需要了解一些window的特…

项目经理有责任,没权利,如何确保项目顺利交付?

由于项目经理在项目中所背负的责任并未被赋予相应的权力&#xff0c;因此在协调资源和组织协同工作方面&#xff0c;他们无法简单地借助权力来解决问题。一旦项目出现问题&#xff0c;不论责任在哪一方&#xff0c;项目经理都首当其冲地需要承担责任。 虽然项目经理看似权力很…

SVN出现Cleanup failed to process the following paths...

SVN报错&#xff0c;需要执行SVN的清理命令clean up&#xff0c;但clean up时出现错误Cleanup failed to process the following paths... 解决办法&#xff1a; 1、clean up的窗口&#xff0c;勾选Break locks和Fix time stamps&#xff08;简单方便&#xff09;&#xff1b…

ESP8266模块常规调试过程讲解

ESP8266-WIFI模块串口调试过程讲解 一、ESP8266介绍 ESP8266是一个高度集成的无线SoC(System on a Chip)模块,基于ESP8266芯片,集成了Wi-Fi功能。具有丰富的特性和功能,广泛应用于各种物联网项目中。 ESP8266模块支持802.11b/g/n无线标准,内置TCP/IP协议栈,可以实现串…

Linux之centos7安装配置及Linux常用命令

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《LInux实战开发》。&#x1f3af;&#x1f3af; …

私有云:【7】VCenter安装Composer服务

私有云&#xff1a;【7】VCenter安装Composer服务 1、创建Composer数据库2、VCenter安装Composer服务2.1、安装Native Client组件2.2、对Composer服务器扩容出一个安装盘 3、安装Composer服务 服务器创建好后配置IP&#xff0c;加入域以及添加域管理员cloudadmin&#xff0c;可…

如何校准振弦采集模块以获得更准确的读数?

如何校准振弦采集模块以获得更准确的读数&#xff1f; 振弦采集模块是一种用于测量振弦传感器输出的模块。在使用振弦采集模块时&#xff0c;校准是非常重要的&#xff0c;因为它可以确保您获得准确的测量结果。本文将介绍如何校准振弦采集模块以获得更准确的读数。 1. 使用标…

华为OD机试 - 堆栈中的剩余数字 - 逻辑分析(Java 2023 B卷 200分)

目录 专栏导读一、题目描述二、输入描述三、输出描述1、输入2、输出3、说明 四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&a…

如何零样本实现语义分割

CLIPTeacher&#xff1a;一种基于VLM的通用零样本语义分割框架&#xff0c;有效地利用了可见和忽略区域&#xff0c;而不需要对原CLIP模型进行任何更改&#xff0c;性能提升显著&#xff01;单位&#xff1a;名古屋大学 现有的通用零样本语义分割&#xff08;GZLSS&#xff09…

校园快递派送互助系统 微信小程序设计与实现

本毕业设计的内容是设计实现一个基于Springboot微信小程序的快递校园帮。使用微信开发者是以java语言进行开发&#xff0c;MYSQL为数据库开发平台&#xff0c;Tomcat网络信息服务作为应用服务器。快递校园帮的功能已基本实现&#xff0c;主要包括有用户、快递员、快递公司、快递…

使用Panda-Gym的机器臂模拟进行Deep Q-learning强化学习

强化学习(RL)是一种机器学习方法&#xff0c;它允许代理通过试错来学习如何在环境中表现。行为主体因采取行动导致预期结果而获得奖励&#xff0c;因采取行动导致预期结果而受到惩罚。随着时间的推移&#xff0c;代理学会采取行动&#xff0c;使其预期回报最大化。 RL代理通常使…

Kubernetes概念及实践

Kubernetes(K8S)中文文档_Kubernetes中文社区 Kubernetes 文档 | Kubernetes K8S 是负责自动化运维管理多个跨机器 Docker 程序的 集群。 kubeadm快速部署K8s集群的工具&#xff0c;如&#xff1a; 创建master node&#xff1a;kubeadm init 将worker node加入到集群中&#x…

Qt 重写QSlider简单实现滑动解锁控件(指定百分比回弹效果)

组件效果图: 应用场景: 用于滑动解锁相关场景,Qt的控件鼠标监听机制对于嵌入式设备GUI可触摸屏依旧可用。 实现方式: 主要是通过继承QSlider以及搭配使用QStyleOptionSlider来实现效果。 注意细则: QStyleOptionSlider是用于定制空白区域是否可移动滑块,根据需求可…

MySQL 到 TiDB:vivo 的 Hive Metastore 横向扩展之路

以下文章来源于公众号 vivo 互联网技术 &#xff0c;作者 Wang Zhiwen 导读 本文介绍了 vivo 在大数据元数据服务横向扩展道路上的探索历程&#xff0c;由实际面临的问题出发&#xff0c;对当前主流的横向扩展方案进行了调研及对比测试&#xff0c;通过多方面对比数据择优选择…

10_4阻塞和非阻塞跟poll和等待队列

阻塞和非阻塞 广泛上的区别就是 应用程序如果非阻塞那读取不到数据就应该马上有返回值 阻塞的话就是在应用程序去read数据,但是设备驱动没有数据,就一直卡住,直到有数据再继续往下 补充阻塞知识,应用层大部分都是阻塞 如果要非阻塞 ,应用程序在打开设备节点的时候填写int fd …

文件夹比较工具怎么用 对比两个文件夹找出多余的文件

在日常工作中&#xff0c;经常会接触到大量的文件&#xff0c;长时间堆积&#xff0c;文件夹会越来越多&#xff0c;从而导致文件重复&#xff0c;如果想要找出想要的文件会比较麻烦&#xff0c;那么你知道应该怎么来查找吗&#xff1f;下面就让我们来学习一下文件夹比较工具怎…

【LeetCode刷题-哈希】-- 705.设计哈希集合

705.设计哈希集合 方法&#xff1a;使用链地址法 设哈希表的大小为base&#xff0c;可以设计一个简单的哈希函数&#xff1a;hash(x) x mod base 开辟一个大小为base的数组&#xff0c;数组的每个位置是一个链表&#xff0c;当计算出哈希值后&#xff0c;就插入到对应位置的…

华为OD机试 - 计算疫情扩散时间 - 矩阵(Java 2023 B卷 200分)

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷&#…