第 2.5 节

嵌入式组C/C++工程基础综合考核题及答案

作者
董佳辉的头像董佳辉
协作者
房梓豪的头像房梓豪
发布于 2025/02/07更新于 2026/08/20

考核完毕后,请将所写的所有文件压成一个压缩包,压缩包名字的格式为 专业班级+姓名(例如:机电2103董佳辉.zip),发到邮箱tungchiahui@gmail.com。

如果邮件被谷歌服务器退回,就发送到邮箱2225279276@qq.com

一、选择题(每题3分,共30分)

题目答案写在记事本中,以.txt的形式提交。

1.用new关键字分配的内存是在以下哪个内存区内?( )

A.静态存储区 B.栈区 C.堆区 D.代码区

2.char * 类型的全局变量如果没有进行初始化,那么程序会讲该变量自动初始化为?()

A.0 B.随机数 C.'\0' ** D.NULL**

3.在C/C++中,以下代码的结果是在终端上显示 a = 273( )

A.对 B.错

unsigned char a = 0b0000000100010001;  //0000 0001 0001 0001
printf("a=%d",a);

4.下方是一个C语言的代码,请问下列选项中错误的是()

typedef struct Student
{
    int8_t name[20];
    int16_t age;
    fp32 score;
}stu;

A. 一个该结构体的变量大小为28字节

B. int8_t是char的别名

C. 代码中Student一般省略不写

D. 代码意思是创建一个Student类型的变量叫stu

5.如果定义了一个数组arr[4],那么(*arr+1)代表的意思是()

A.数组0号元素的值

B.数组0号元素的地址(指针)

C.数组1号元素的值

D.数组1号元素的地址(指针)

E.数组0号元素的值+1

6.宏__cplusplus是工程中若有.cpp文件会自动定义( )

A.对 B.错

7.联合体union变量所占的内存大小为( )

A.4字节

B.所占内存最大的成员变量的大小

C.根据不同的字长,拥有不同的大小

D.所有成员变量所占内存大小之和

8.this指针存在的目的是( )

A. 保证基类共有成员在子类中可以被访问

B. 保证基类保护成员在子类中可以被访问

C. 保证每个对象拥有自己的数据成员,但共享处理这些数据成员的代码

D. 保证基类私有成员在子类中可以被访问

9.下列关于构造函数的特点,其中描述错误的是( )

A. 构造函数是一种成员函数,它具有一般成员函数的特点

B. 构造函数必须指明其类型

C. 构造函数的名称与其类名相同

D. 一个类中可以定义一个或多个构造函数

10.以下是FreeRTOS中控制机器人底盘前进的线程源码,请分析下面代码中BSP_CAN是什么( )

//底盘控制任务(FreeRTOS线程)
void chassis_task(void const * argument)
{
    CONTROL_ALGO::PID_devices_Init();   //底盘电机PID算法初始化
    CAN_BUS::BSP_CAN::CAN1_Init();      //CAN1通信总线初始化
    CAN_BUS::BSP_CAN::CAN2_Init();      //CAN2通信总线初始化
    while(true)
    {
        //大疆电机负反馈闭环控制4个电机保持500rpm转速
        DJI_RM_MOTOR::CMD::CAN_1::Front(CONTROL_ALGO::PID_velocity_realize_1(500,1),
                                        CONTROL_ALGO::PID_velocity_realize_1(500,2),
                                        CONTROL_ALGO::PID_velocity_realize_1(500,3),
                                        CONTROL_ALGO::PID_velocity_realize_1(500,4));
        osDelay(1);   //RTOS延时1ms
    }
}


//调用
{
stu.xxx();
pstu->xxx();


ns_demo::xxx();
}

//定义
void stu::xxx(void)

A.类 B.结构体 ** C.命名空间 ** D.联合体

image\.png

二、程序题

提交源文件.cpp,源文件以题号命名。

第13题提交压缩包,压缩包内要有main.cpp和库的文件,压缩包以题号命名。

11.利用海伦公式求三角形面积(10分=数学逻辑5+其他5)

海伦公式是这样的,如果一个三角形的三边长为a,b,c,设p=(a+b+c)/2,则三角形的面积:

image\.png

image\.png

image\.png

#include <iostream>
#include <cmath>
#include <stdlib.h>

using std::cout;
using std::cin;
using std::endl;

int main()
{
    double a, b, c, p, area;
    cout << "请输入3条边长:";
    cin >> a >> b >> c;
    if (a + b > c && b + c > a && a + c > b)
    {
        p = (a + b + c) / 2.0;
        area = sqrt(p * (p - a) * (p - b) * (p - c));
        cout << "三角形的面积是:" << area << endl;
    }
    else
        cout << "这3个数无法组成三角形!" << endl;
    system("pause");
    return 0;
}

12.分解质因数(10分=数学逻辑5+其他5)

将一个整数分解质因数。例如:输入90,打印出90=2*3*3*5

image\.png

#include <iostream>
#include <stdlib.h>

using std::cout;
using std::cin;
using std::endl;

int main()
{
    int i, n;
    cout << "输入需要分解的整数:";
    cin >> n;
    cout << "分解后的结果是:";
    for (i = 2; i <= n; i++)
    {
        while (n % i == 0)
        {
            cout << i;
            n /= i;
            if (n != 1)
            {
                cout << "*";
            }
        }
    }
    cout << endl;
    system("pause");
    return 0;
}

13.基础应用(20分=库5+类5+命名空间5+数组等其他5)

①请定义一个叫class_lib的库(class_lib.cpp和class_lib.h)。

②class_lib库内有一个命名空间叫person_ns。

③person_ns命名空间中声明定义了一个类叫Staff。Staff该类有私有的成员变量有name(姓名),age年龄,salary(工资)。

该类中有个公开方法print_info,print_info方法用于打印Staff类型的对象(变量)的所有成员变量。

④person_ns命名空间中还有1个函数是scan_info,该函数是class Staff的友元。

scan_info函数的返回值为void,用于给Staff对象的所有成员变量赋值。

⑤请在main.cpp的主函数中在堆区创建n个Staff类型的对象(变量)(n由键盘输入),然后给这n个Staff类型的对象(变量)的所有成员变量都赋值,并打印。

image\.png

main.cpp

#include <iostream>
#include "class_lib.h"
using std::cout;
using std::cin;
using std::endl;

int main()
{
        int n;
        cout << "请输入一共有多少个职工,n=";
        cin >> n;
        person_ns::Staff* staff_arr = new person_ns::Staff[n];
        for (int i = 0; i < n; i++)
        {
                cout << "请输入第" << i + 1 << "个职工的信息:";
                person_ns::scan_info(&staff_arr[i]);
        }
        for (int i = 0; i < n; i++)
        {
                cout << "打印第" << i + 1 << "个职工的信息:";
                staff_arr[i].print_info();
        }
        delete []staff_arr;
        return 0;
}

class_lib.cpp

#include "class_lib.h"

using std::cout;
using std::cin;
using std::endl;

void person_ns::scan_info(Staff* p)
{
        cout << "请输入姓名:";
        cin >> p->name;
        cout << "请输入年龄:";
        cin >> p->age;
        cout << "请输入工资:";
        cin >> p->salary;
}

void person_ns::Staff::print_info(void)
{
        cout << "该职工姓名为:" << this->name << endl;
        cout << "该职工年龄为:" << this->age << endl;
        cout << "该职工工资为:" << this->salary << endl;

}

class_lib.h

#ifndef __CLASS_LIB_H_
#define __CLASS_LIB_H_

#include <iostream>
#include <string>

namespace person_ns
{
        class Staff
        {
                public:
                        std::string name;
                        short age;
                        float salary;
                        void print_info(void);
                        friend void scan_info(Staff* p);
        };
        void scan_info(Staff* p);
}

#endif

image\.png

14.OOP(面向对象)(15分=继承5+多态5+其他5):

①定义一个父类(基类)为Animal,该类中有一个受保护的成员变量name(动物的名字),还有两个公开的方法分别为print_name和make_sound。

print_name用来打印name变量。

make_sound用来打印一串字符串“动物叫!”

该类还有一个构造函数,构造函数用来给name变量传值。

该类还有一个析构函数,用来打印字符串“基类动物类析构函数运行!”

②定义一个子类(派生类)为Dog(公开继承Animal类),该类只有一个公开方法为make_sound。

make_sound用来打印一串字符串“狗叫!” 该类还有一个构造函数,构造函数用来给name变量传值。 该类还有一个析构函数,用来打印字符串“派生类狗类析构函数运行!”

③定义一个子类(派生类)为Cat(公开继承Animal类),该类仅有一个公开方法为make_sound。 make_sound用来打印一串字符串“猫叫!” 该类还有一个构造函数,构造函数用来给name变量传值。 该类还有一个析构函数,用来打印字符串“派生类猫类析构函数运行!”

④有一个函数为void print_animal_info(Animal *p) **或者 ** void print_animal_info(std::shared_ptr<Animal> p),该函数的作用是调用指针形参p **或者 **智能指针形参p的print_name和make_sound方法。

⑤在main.cpp的主函数中,在栈区 或者 堆区创建一个Dog类对象和一个Cat类对象("狗"对象叫“旺财”,"猫"对象叫“阿橘”)

⑥在主函数中调用两次print_animal_info函数,入口参数分别使用刚才创建的两个对象。(多态调用)

image\.png

方法一(栈区、局部变量):

#include <iostream>
#include <string>

using std::cout;
using std::cin;
using std::endl;

class Animal
{
public:
    Animal(std::string animal_name);
    virtual ~Animal();
    void print_name(void);
    virtual void make_sound(void);
protected:
    std::string name;
};

class Dog : public Animal
{
public:
    Dog(std::string dog_name);
    ~Dog();
    void make_sound(void);
};

class Cat : public Animal
{
public:
    Cat(std::string cat_name);
    ~Cat();
    void make_sound(void);
};

void print_animal_info(Animal* p);

int main()
{
    Dog dog_("旺财");
    Cat cat_("阿橘");
    print_animal_info(&dog_);
    print_animal_info(&cat_);
    return 0;
}


Animal::Animal(std::string animal_name)
{
    this->name = animal_name;
}

Animal::~Animal()
{
    cout << "基类动物类析构函数运行!" << endl;
}

void Animal::print_name(void)
{
    cout << "该动物的名字叫" << this->name << endl;
}

void Animal::make_sound(void)
{
    cout << "动物叫!" << endl;
}




Dog::Dog(std::string dog_name) : Animal(dog_name)
{

}

Dog::~Dog()
{
    cout << "派生类狗类析构函数运行!" << endl;
}

void Dog::make_sound(void)
{
    cout << "狗叫!" << endl;
}


Cat::Cat(std::string cat_name) : Animal(cat_name)
{

}

Cat::~Cat()
{
    cout << "派生类猫类析构函数运行!" << endl;
}

void Cat::make_sound(void)
{
    cout << "猫叫!" << endl;
}


void print_animal_info(Animal* p)
{
    p->print_name();
    p->make_sound();
}

方法二(堆区、智能指针):

#include <iostream>
#include <string>
#include <memory>

using std::cout;
using std::cin;
using std::endl;

class Animal
{
public:
    Animal(std::string animal_name);
    virtual ~Animal();
    void print_name(void);
    virtual void make_sound(void);
protected:
    std::string name;
};

class Dog : public Animal
{
public:
    Dog(std::string dog_name);
    ~Dog();
    void make_sound(void);
};

class Cat : public Animal
{
public:
    Cat(std::string cat_name);
    ~Cat();
    void make_sound(void);
};

void print_animal_info(std::shared_ptr<Animal> p);

int main()
{
    auto dog_ = std::make_shared<Dog>("旺财");
    auto cat_ = std::make_shared<Cat>("阿橘");
    print_animal_info(std::static_pointer_cast<Animal>(dog_));
    print_animal_info(std::static_pointer_cast<Animal>(cat_));
    return 0;
}

Animal::Animal(std::string animal_name)
{
    this->name = animal_name;
}

Animal::~Animal()
{
    cout << "基类动物类析构函数运行!" << endl;
}

void Animal::print_name(void)
{
    cout << "该动物的名字叫" << this->name << endl;
}

void Animal::make_sound(void)
{
    cout << "动物叫!" << endl;
}




Dog::Dog(std::string dog_name) : Animal(dog_name)
{

}

Dog::~Dog()
{
    cout << "派生类狗类析构函数运行!" << endl;
}

void Dog::make_sound(void)
{
    cout << "狗叫!" << endl;
}


Cat::Cat(std::string cat_name) : Animal(cat_name)
{

}

Cat::~Cat()
{
    cout << "派生类猫类析构函数运行!" << endl;
}

void Cat::make_sound(void)
{
    cout << "猫叫!" << endl;
}


void print_animal_info(std::shared_ptr<Animal> p)
{
    p->print_name();
    p->make_sound();
}

15.函数高级应用与函数模板(15分=函数重载函数模板5+变量内存位置5+函数默认参数等其他5)

①请声明定义一个函数add,入口参数为3个整形变量,第三个入口参数可不填且不填时默认第三个入口参数为0;该函数返回值是3个入口参数相加后的结果。

②请再声明定义一个函数add,入口参数为3个短****整型变量,第三个入口参数可不填且不填时默认第三个入口参数为0;该函数返回值是3个入口参数相加后的结果。

③请再定义一个函数模板,函数名为add,占位符为T,要求该函数模板也能完成①②两个函数的功能。

④请在main.cpp中

定义三个整形变量并赋值(要求定义成全局变量),

再定义两个短整型变量并赋值(要求定义成栈区变量),

再定义两个单精度浮点型变量并赋值(要求在堆区储存变量)。

⑤请在主函数中使用上面①②③的函数算出三个整型、两个短整型、两个单精度浮点型变量分别相加后的结果,并打印。

image\.png

#include <iostream>
#include <string>
#include <memory>

using std::cout;
using std::cin;
using std::endl;


int add(int a, int b, int c = 0);
short add(short a, short b, short c = 0);

template<typename T>
T add(T a, T b, T c = 0);

int main()
{
    static int a, b, c;
    short x, y;
    auto m = std::make_shared<float>();
    auto n = std::make_shared<float>();
    cout << "请输入三个整形变量的值:";
    cin >> a >> b >> c;
    cout << "请输入两个短整形变量的值:";
    cin >> x >> y;
    cout << "请输入两个单精度浮点型变量的值:";
    cin >> *m >> *n;
    cout << "三个整形变量相加后的结果是:" << add(a, b, c) << endl;
    cout << "两个短整形变量相加后的结果是:" << add(x, y) << endl;
    cout << "两个单精度浮点型变量相加后的结果是:" << add<float>(*m, *n) << endl;
//    cout << "两个单精度浮点型变量相加后的结果是:" << add(*m, *n) << endl;   //这种方法也可以,让编译器自己判断T是什么
    return 0;
}

int add(int a, int b, int c)
{
    return a + b + c;
}

short add(short a, short b, short c)
{
    return a + b + c;
}

template<typename T>
T add(T a, T b, T c)
{
    return a + b + c;
}

image\.png

三、附加题

16.现代C++

请你设计一个“计算器系统”,包括:

  1. 一个基类 BaseCalculator,用于统一接口,内部拥有一个 std::function<int(int,int)> 类型的回调函数 callback_。

  2. 提供 set_callback 和 get_callback 两个接口来设置和获取这个回调函数。

  3. 提供一个 do_calculation(int x, int y) 函数,调用 callback_ 进行计算并打印结果。

然后设计两个派生类:

🔹 类 AddCalculator:

  • 在构造函数中,将自身的 add(int, int) 成员函数通过 bind 绑定为回调。

  • add 函数返回两数之和。

🔹 类 MultiplyCalculator:

  • 本类里不准出现multiply(int, int)这种乘法函数。

  • 在构造函数中,请直接将 lambda表达式 绑定为回调。

最终在 main() 中:

  1. 在堆区创建 AddCalculator 对象并调用 do_calculation(10, 5) → 输出结果为 15

  2. 在堆区创建 MultiplyCalculator 对象并调用 do_calculation(10, 5) → 输出结果为 50

  3. 将 AddCalculator 的回调借给 MultiplyCalculator,再调用 do_calculation(10, 5) → 输出结果为 15

image\.png

#include <iostream>
#include <functional>
#include <memory>

// 基类
class BaseCalculator
{
public:
    void set_callback(std::function<int(int,int)> cb)
    {
        callback_ = std::move(cb);
    }

    std::function<int(int,int)> get_callback() const
    {
        return callback_;
    }

    void do_calculation(int x, int y)
    {
        if (callback_)
        {
            int result = callback_(x, y);
            std::cout << "Result: " << result << std::endl;
        }
    }

private:
    std::function<int(int,int)> callback_;
};

// 派生类:加法
class AddCalculator : public BaseCalculator
{
public:
    AddCalculator()
    {
        set_callback(std::bind(&AddCalculator::add,this,std::placeholders::_1, std::placeholders::_2));
    }

private:
    int add(int a, int b)
    {
        return a + b;
    }
};

// 派生类:乘法
class MultiplyCalculator : public BaseCalculator
{
public:
    MultiplyCalculator()
    {
        set_callback([this](int a, int b)
        {
            return a * b;
        });
    }

};

// 主函数
int main()
{
    auto add_calc = std::make_shared<AddCalculator>();
    auto mul_calc = std::make_shared<MultiplyCalculator>();

    add_calc->do_calculation(10, 5);   // 输出 15
    mul_calc->do_calculation(10, 5);   // 输出 50

    // 用加法替换乘法的回调
    mul_calc->set_callback(add_calc->get_callback());
    mul_calc->do_calculation(10, 5);   // 输出 15

    return 0;
}