当前位置: 首页 > 知识库问答 >
问题:

C++中各种类的无效指针

辛成周
2023-03-14

背景:

  1. 我有C背景,刚开始在嵌入式项目中使用C++。
  2. 我编写了一个能够处理多个设备的固件,具体取决于最终用户获得设备之前如何通过图形界面配置固件。
  3. 每个设备类型由一个类表示。
  4. 许多参数在多个(但不是所有)类型的器件之间共享(即电池电平),一些功能也共享(即从EEPROM读取特定于器件类型的内容)。

目标:

能够通过指针访问函数和变量,而不必不断转换void指针。

在调用函数之前,我不应该知道我使用的是什么类型的设备吗?

嗯,是的,我想,但让我们考虑以下几点。

void * _type;
uint8_t deviceType = getDeviceTypeFromEEPROM();

//somewhere at the beginning
switch(deviceType)
{
        case DEVICE_A:
            _type = new DeviceA();
            break;
        case DEVICE_B:
            _type = new DeviceB();
            break;
}

//somewhere during execution. 
//I want to avoid having to do something like this. 2 types in example, in reality I have over 10. 
//I would prefer not to put a switch and cast every time I need flexibility.
switch(deviceType)
{
        case DEVICE_A:
            static_cast<DeviceA*>(_type)->readEEPROM();
            break;

        case DEVICE_B:
            static_cast<DeviceB*>(_type)->readEEPROM();
            break;
}

设想的解决方案:

有一个基类并使用虚函数。变量呢?我是否需要有虚函数来访问驻留在不同类中的变量?

其他解决方案:

对任何其他解决方案都是开放的。

共有1个答案

龙欣德
2023-03-14

下面是我如何实现OOP风格解决方案的草图;没有什么特别的,只是程序支持的不同类型参数的枚举,以及idevice接口,该接口表示知道如何设置或获取这些类型的值的任何设备。然后,您可以根据需要为具有特定于该设备类型的参数的设备实现子类:

enum class ParameterType {
   BatteryLevel,
   Uptime,
   SerialNumber,
   DeviceAProprietarySetting,
   DeviceBProprietarySetting,
   // [... add more values here as necessary...]
};

typedef std::variant<int, float, std::string> ParameterValue;

// Abstract interface to any device 
// (so you can pass around IDevice* pointers instead of void* pointers)
class IDevice
{
public:
   IDevice() {}
   virtual ~IDevice() {}

   /** Subclass should implement this to write the specified parameter-value
     * into (retValue) and return true... or if it cannot (e.g. because it
     * doesn't support that particular parameter-value), it should return
     * false to indicate failure.
     */
   virtual bool GetValue(ParameterType pt, ParameterValue & retValue) const = 0;

   /** Subclass should implement this to accept the specified parameter-value
     * from (newValue) and return true... or if it cannot (e.g. because it
     * doesn't support that particular parameter-value), it should return
     * false to indicate failure to set anything.
     */
   virtual bool SetValue(ParameterType pt, const ParameterValue & newValue) = 0;

   // more virtual methods could be added here, if there are other actions
   // that most of your devices support
};

// Since most devices have these parameters, we'll move them up into a shared
// base class to avoid having to reimplement that functionality for every device
class TypicalDevice : public IDevice
{
   TypicalDevice() {}

   virtual bool GetValue(ParameterType pt, ParameterValue & retValue) const
   {
      switch(pt)
      {
         case ParameterType::BatteryLevel: retValue = _batteryLevel; return true;
         case ParameterType::Uptime:       retValue = _uptime;       return true;
         case ParameterType::SerialNumber: retValue = _serialNumber; return true;
         default:                          return false;  // ParameterType not found!
      }
   }

   virtual bool SetValue(ParameterType pt, const ParameterValue & newValue)
   {
      switch(pt)
      {
         case ParameterType::BatteryLevel: _batteryLevel = std::get<float>(newValue);       return true;
         case ParameterType::Uptime:       _uptime;      = std::get<int>(newValue)          return true;
         case ParameterType::SerialNumber: _serialNumber = std::get<std::string>(newValue); return true;
         default:                          return false;  // ParameterType not found!
      }
   }

private:
   float _batteryLevel;
   int _uptime;  // in seconds?
   std::string _serialNumber;
};

// Implementation for some specific device-type
class DeviceA : public TypicalDevice
{
   DeviceA() {}

   virtual bool GetValue(ParameterType pt, std::variant & retValue) const
   {
      switch(pt)
      {
         case ParameterType::DeviceAProprietarySetting: retValue = _deviceAProprietarySetting; return true;

         default:
            return TypicalDevice::GetValue(pt, retValue);
      }
   }

   virtual bool SetValue(ParameterType pt, const std::variant & newValue)
   {
      switch(pt)
      {
         case ParameterType::DeviceAProprietarySetting: _deviceAProprietarySetting = std::get<float>(newValue); return true;

         default:
            return TypicalDevice::GetValue(pt, retValue);
      }
   }

private:
   float _deviceAProprietarySetting;
};
 类似资料:
  • 问题内容: TLDR: 是否有Java等效于C#的委托,这使我可以排队各种类的方法并将其动态添加到队列中?语言构造而不是代码。 内容: 我以前使用过Unity 3D,并且喜欢 脚本方法。只需声明该方法即可将其添加到每帧执行的方法列表中。我想在我的LWJGL游戏中创建类似的内容。为此,我想使用委托(或与其等效的东西)。是否有任何Java语言构造可以允许我执行此操作?我希望答案包括两个或多个(以便我可

  • 实现指南 Pact workshop - 两小时从零起步掌握Pact 这些workshop可以带你从头到尾完成一个例子,涉及Pact支持的大部分概念。我们现在有Ruby、JVM和Android等workshop: Ruby JVM Android 支持的语言 Ruby JVM .NET Javascript Go Swift / Objective-C

  • C++ 类 & 对象 一个指向 C++ 类的指针与指向结构的指针类似,访问指向类的指针的成员,需要使用成员访问运算符 ->,就像访问指向结构的指针一样。与所有的指针一样,您必须在使用指针之前,对指针进行初始化。 下面的实例有助于更好地理解指向类的指针的概念: #include <iostream> using namespace std; class Box { public:

  • 本文向大家介绍浅析C++的引用与const指针与各种传递方式,包括了浅析C++的引用与const指针与各种传递方式的使用技巧和注意事项,需要的朋友参考一下 浅析C++的引用与const指针与各种传递方式 首先我们知道 const int *p 与 int const *p 是一样的,即 *p 是常量;而 int * const p 跟上面是不一样的,即 p 是常量;我们知道引用只是一个别名,与变量

  • 项目 package.json 文件中通常会包含多种依赖,如下: { "name":"my-project", "dependencies":{ "package-a":"^1.0.0" }, "devDependencies":{ "package-b":"^1.2.1" }, "peerDependencies":{ "package-c":"^2.5.4" }, "

  • 本文向大家介绍C++实现各种排序算法类汇总,包括了C++实现各种排序算法类汇总的使用技巧和注意事项,需要的朋友参考一下 C++可实现各种排序算法类,比如直接插入排序、折半插入排序、Shell排序、归并排序、简单选择排序、基数排序、对data数组中的元素进行希尔排序、冒泡排序、递归实现、堆排序、用数组实现的基数排序等。 具体代码如下: