提问者:小点点

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


背景:

  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个答案

匿名用户

下面是我如何实现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;
};

相关问题


MySQL Query : SELECT * FROM v9_ask_question WHERE 1=1 AND question regexp '(c++|中|种类|无效|指针)' ORDER BY qid DESC LIMIT 20
MySQL Error : Got error 'repetition-operator operand invalid' from regexp
MySQL Errno : 1139
Message : Got error 'repetition-operator operand invalid' from regexp
Need Help?