C++统一的自测接口实践

 更新时间:2026年05月23日 10:31:44   作者:IOT-Power  
这篇文章主要介绍了C++统一的自测接口实践,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

可以,而且这是很常见的做法。关键不是让 CameraDevice 继承一个具体的 CameraSelfTest,而是让它继承一个统一的自测接口

也就是:

CameraDevice 继承 ISelfTest
ModbusDevice 继承 ISelfTest
TcpDevice    继承 ISelfTest

然后统一放到 ISelfTest* 数组里遍历调用 SelfTest()

一、推荐结构

ISelfTest
   |
   |-- CameraDevice
   |-- ModbusDevice
   |-- TcpDevice
   |-- CanDevice

这样每个设备自己实现自己的自测逻辑,外部统一这样调用:

selfTests[i]->SelfTest();

二、完整 C++ 例子,不使用 std

#include <stdio.h>

#define SELF_TEST_OK      0
#define SELF_TEST_FAILED  1

// =====================================================
// 1. 自测接口
// =====================================================
class ISelfTest
{
public:
    virtual ~ISelfTest()
    {
    }

    virtual int SelfTest() = 0;
    virtual const char* GetSelfTestName() = 0;
};

// =====================================================
// 2. 摄像头设备
// CameraDevice 本身具备自测能力
// =====================================================
class CameraDevice : public ISelfTest
{
public:
    void Start()
    {
        printf("CameraDevice Start\n");
    }

    void Stop()
    {
        printf("CameraDevice Stop\n");
    }

    int CheckImage()
    {
        printf("CameraDevice Check Image\n");
        return 1;
    }

    int CheckFrameRate()
    {
        printf("CameraDevice Check Frame Rate\n");
        return 1;
    }

    const char* GetSelfTestName()
    {
        return "CameraDevice SelfTest";
    }

    int SelfTest()
    {
        printf("========== CameraDevice SelfTest Start ==========\n");

        Start();

        if (CheckImage() == 0)
        {
            printf("CameraDevice SelfTest Failed: Image Error\n");
            Stop();
            return SELF_TEST_FAILED;
        }

        if (CheckFrameRate() == 0)
        {
            printf("CameraDevice SelfTest Failed: FrameRate Error\n");
            Stop();
            return SELF_TEST_FAILED;
        }

        Stop();

        printf("CameraDevice SelfTest OK\n");
        return SELF_TEST_OK;
    }
};

// =====================================================
// 3. Modbus设备
// ModbusDevice 本身也具备自测能力
// =====================================================
class ModbusDevice : public ISelfTest
{
public:
    void Open()
    {
        printf("ModbusDevice Open Serial Port\n");
    }

    void Close()
    {
        printf("ModbusDevice Close Serial Port\n");
    }

    int CheckConnection()
    {
        printf("ModbusDevice Check Connection\n");
        return 1;
    }

    int CheckRegister()
    {
        printf("ModbusDevice Check Register\n");
        return 1;
    }

    const char* GetSelfTestName()
    {
        return "ModbusDevice SelfTest";
    }

    int SelfTest()
    {
        printf("========== ModbusDevice SelfTest Start ==========\n");

        Open();

        if (CheckConnection() == 0)
        {
            printf("ModbusDevice SelfTest Failed: Connection Error\n");
            Close();
            return SELF_TEST_FAILED;
        }

        if (CheckRegister() == 0)
        {
            printf("ModbusDevice SelfTest Failed: Register Error\n");
            Close();
            return SELF_TEST_FAILED;
        }

        Close();

        printf("ModbusDevice SelfTest OK\n");
        return SELF_TEST_OK;
    }
};

// =====================================================
// 4. 统一遍历执行自测
// =====================================================
void RunAllSelfTest(ISelfTest* selfTests[], int count)
{
    int i = 0;

    for (i = 0; i < count; i++)
    {
        if (selfTests[i] == NULL)
        {
            continue;
        }

        printf("\nRun %s\n", selfTests[i]->GetSelfTestName());

        int result = selfTests[i]->SelfTest();

        if (result == SELF_TEST_OK)
        {
            printf("Final Result: OK\n");
        }
        else
        {
            printf("Final Result: FAILED\n");
        }
    }
}

// =====================================================
// 5. main 测试
// =====================================================
int main()
{
    CameraDevice camera;
    ModbusDevice modbus;

    ISelfTest* selfTests[10];
    int count = 0;

    selfTests[count++] = &camera;
    selfTests[count++] = &modbus;

    RunAllSelfTest(selfTests, count);

    return 0;
}

三、重点理解这句

ISelfTest* selfTests[10];

这个数组里面放的不是具体设备类型,而是统一的自测接口指针。

所以你可以放:

selfTests[count++] = &camera;
selfTests[count++] = &modbus;

虽然 camera 是:

CameraDevice camera;

modbus 是:

ModbusDevice modbus;

但它们都继承了:

ISelfTest

所以都可以被当成:

ISelfTest*

来统一管理。

四、这种方式叫什么?

这个核心是:

接口 + 多态

不是工厂模式。

外部统一调用:

selfTests[i]->SelfTest();

但是实际执行的是:

CameraDevice::SelfTest()
ModbusDevice::SelfTest()

这就是 C++ 的虚函数多态。

五、你不要这样设计

不建议这样:

class CameraDevice : public CameraSelfTest
{
};

因为这样会变成:

设备继承具体自测类

逻辑会比较别扭。

更合理的是:

class CameraDevice : public ISelfTest
{
public:
    int SelfTest();
};

也就是:

设备继承自测接口
设备自己实现自己的自测逻辑

六、如果你的设备本来已经有父类怎么办?

比如你原来已经有:

class CDevice
{
public:
    virtual void Start() = 0;
    virtual void Stop() = 0;
};

那也可以这样:

class CameraDevice : public CDevice, public ISelfTest
{
public:
    void Start();
    void Stop();

    int SelfTest();
    const char* GetSelfTestName();
};

这是多继承,但这里继承的是接口类,问题不大。

七、什么时候适合这样做?

适合你的情况:

10 种设备都需要自测
自测就是设备自身能力的一部分
希望后面可以统一遍历调用

最终用法就是:

ISelfTest* selfTests[10];

selfTests[0] = &camera;
selfTests[1] = &modbus;
selfTests[2] = &tcp;
selfTests[3] = &can;

RunAllSelfTest(selfTests, 4);

这个结构很清楚。设备自己负责自己的自测,外部只负责统一调度。

八、总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • FFmpeg获取网络摄像头数据解码

    FFmpeg获取网络摄像头数据解码

    这篇文章主要为大家详细介绍了FFmpeg获取网络摄像头数据解码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-06-06
  • C语言 数据结构中栈的实现代码

    C语言 数据结构中栈的实现代码

    这篇文章主要介绍了C语言 数据结构中栈的实现代码的相关资料,需要的朋友可以参考下
    2016-10-10
  • 基于C++实现的各种内部排序算法汇总

    基于C++实现的各种内部排序算法汇总

    这篇文章主要介绍了基于C++实现的各种内部排序算法,非常经典,需要的朋友可以参考下
    2014-08-08
  • C语言杨氏矩阵简单实现方法

    C语言杨氏矩阵简单实现方法

    杨氏矩阵是一个数字矩阵,矩阵的每一行从左到右一次递增,矩阵从上到下递增,在这样的矩阵中查找一个数字是否存在。时间复杂度小于O(N),有需要的朋友可以借鉴参考下
    2023-02-02
  • FFmpeg实现音频渐响效果参数值详解

    FFmpeg实现音频渐响效果参数值详解

    这篇文章主要为大家介绍了FFmpeg实现音频渐响效果参数值详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • Windows下CMake的下载与安装过程

    Windows下CMake的下载与安装过程

    CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程),这篇文章主要介绍了Windows下CMake的下载与安装,需要的朋友可以参考下
    2022-02-02
  • C语言形参与实参使用的差别讲解

    C语言形参与实参使用的差别讲解

    形参出现在函数定义中,在整个函数体内都可以使用, 离开该函数则不能使用。实参出现在主调函数中,进入被调函数后,实参变量也不能使用,形参和实参的功能是作数据传送。发生函数调用时, 主调函数把实参的值传送给被调函数的形参从而实现主调函数向被调函数的数据传送
    2023-02-02
  • C语言实现影院管理系统

    C语言实现影院管理系统

    这篇文章主要为大家详细介绍了C语言实现影院管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-12-12
  • C++多线程之互斥锁与死锁

    C++多线程之互斥锁与死锁

    互斥锁和死锁是C++多线程中常见的情况,这篇文章就带大家进一步了解多线程中的互斥锁与死锁这两个概念,文中的示例代码介绍得很详细,快来跟随小编一起学习吧
    2021-12-12
  • C语言中等待socket连接和对socket定位的方法

    C语言中等待socket连接和对socket定位的方法

    这篇文章主要介绍了C语言中等待socket连接和对socket定位的方法,分别为listen()函数和bind()函数的用法,需要的朋友可以参考下
    2015-09-09

最新评论