如何调用在一个类中创建然后传递给另一个类的 C++ 函数指针?

问题描述

我把自己编程到了一个角落,在这个过程中,我意识到我真的缺乏对 C++ 函数指针和虚函数的理解。目标是在树莓派上实现温度控制器。我不会详细介绍其他组件,因为它们不相关。我目前正在研究按钮控制器。这更像是一个架构问题。

  • TempCtrl 是调用所有其他类的主类。它还调用 ButtonController::addButton() 来注册按钮,并包含回调。
  • ButtonCtrl 读取 gpio 寄存器并循环浏览存储在 Button 类型向量中的注册按钮。
  • Button 类应该是一个非常简单的容器,它只有一个指定 gpio 和回调的整数。这就是问题所在。

我以前从未真正做过这样的事情,但我想要一些非常干净的东西。基本上,一旦我完成了按钮控制器,我就希望能够不理会它,除非我添加功能。为此,我希望在 TempCtrl 函数中定义回调函数

到目前为止,这还没有奏效。如果可能的话,我确定我的语法是关闭的。我也对实现这一目标的其他方法感兴趣。

代码如下。我只贴了相关的header,以及buttoncontroller.cpp,因为有很多代码。如果需要更多信息,我很乐意发布更多代码,所以请询问:

button.hpp

#ifndef BUTTON_HPP
#define BUTTON_HPP

#include <ctime>
#include <cstdint>

#define HOLDTIME    500  // milliseconds

class TempCtrl;

enum State_E
{
  BP_LOW,BP_HIGH
};

class Button
{
  public:
  Button(
    uint8_t _gpio,void(TempCtrl::*)(),void(TempCtrl::*)());

  ~Button();

  void update(State_E newValue);

  uint8_t getGpio() const;

  private:
  void (TempCtrl::*onFallingEdge)();

  void (TempCtrl::*onLongHold)();

  void (TempCtrl::*onRisingEdge)();
  
  uint8_t gpio;

  State_E state;

  time_t timeStamp;
};

#endif /* BUTTON_HPP */

buttonprocessor.hpp

#ifndef BUTTONPROCESSOR_HPP
#define BUTTONPROCESSOR_HPP

#include "button.hpp"
#include <cstdint>
#include <vector>

#define GPIO_MAX    53
#define BLOCK_SIZE  (4*1024)
#define GPLEV0      13
#define GPLEV1      14
#define SCAN_RATE   100  // milliseconds

class ButtonProcessor
{
  public:
  ButtonProcessor();

  virtual ~ButtonProcessor();

  bool init();

  bool shutdown();
  
  size_t addButton(Button button);

  void startEventLoop(bool &terminate);

  private:

  int fd; 

  volatile uint32_t *gpio_base;

  std::vector<Button> buttonDb;
};

#endif /* BUTTONPROCESSOR_HPP */

tempctrl.hpp

#ifndef TEMPCTRL_HPP
#define TEMPCTRL_HPP
#include "button.hpp"
#include "lcdscreen.hpp"
#include "buttonprocessor.hpp"

#include <cstdlib>
#include <vector>
#include <string>
#include <time.h>
#include <cstring>
#include <memory>

#define W1_DEV_ROOT "/sys/bus/w1/devices/w1_bus_master1/"
#define W1_SLAVE_COUNT W1_DEV_ROOT "w1_master_slave_count"
#define W1_SLAVES W1_DEV_ROOT "w1_master_slaves"
#define POLL_FREQ 1000

/***********************************************
*  A structure for holding a single data point *
*  of temperature in degrees celsius,as well  *
*  as the temp probe ID and a time stamp.      *
************************************************/

struct TempStruct
{
  time_t      ts;
  std::string id;
  float       temp;
};

enum TScale_E
{
  CELSIUS,fareNHEIT,KELVIN,RANKINE,MAX_VALUE_TSCALE
};

#define DEFAULT_TEMP_SCALE fareNHEIT

enum InputMode_E
{
  SETPOINT,LOAD_PROFILE,PID_TUNE,MAX_VALUE_INPUT_MODE
};

class TempCtrl 
{   
public:
  TempCtrl();
    
  virtual ~TempCtrl();
    
  /***********************************************
  *  Fetches the current time from the specified *
  *  temperature controller,and stores the      *
  *  returned value with time stamp and device   *
  *  id,in the tempStruct array.    
  ************************************************/
  void getTemp(int);

  void setTempScale(TScale_E);

  void lcdToggleEnable(int bits);

  void wait(size_t seconds);

  void printTemp(enum TScale_E);

  std::vector<std::string> slavesArr;

  std::vector<TempStruct> tempStruct;

  TScale_E tempScaleVal = CELSIUS;

  int fd;

// These should not be public 
  void onFallingEdge();

  void onLongHold();

  void onRisingEdge();

private:
  void lcdInit();

  uint8_t tempInit(void);

  /***********************************************
  * exclusive access to atomic safe lcdscreen    *
  * manipulation.  Logic is completely decoupled *
  ************************************************/
  std::unique_ptr<LcdScreen> mLcdScreen;

  /***********************************************
  * The responsibility of the button processor   *
  * is to detect edge changes in for specified   *
  * GPIO's,determine the type of press and call *
  * the relavant callback.                       * 
  ************************************************/
  std::unique_ptr<ButtonProcessor> mButtonProcessor;

};
#endif /* TEMPCTRL_HPP */

buttonprocessor.cpp

#include "button.hpp"

Button::Button(
    uint8_t _gpio,void(TempCtrl::*_onFallingEdge)(),void(TempCtrl::*_onLongHold)(),void(TempCtrl::*_onRisingEdge)())
: state(BP_LOW),timeStamp(time(NULL)),onFallingEdge(_onFallingEdge),onLongHold(_onLongHold),onRisingEdge(_onRisingEdge)
{
  
}
  
Button::~Button()
{ 
  
}

void Button::update(State_E newValue)
{   
  if(
    newValue != state &&
    state == BP_HIGH) // Rising edge
  { 
    timeStamp = time(NULL);
    state = newValue;
    // ((Button*)this)->Button::onRisingEdge(); 
  }
  else if(
    state == BP_HIGH && 
    newValue == state &&
    ((time(NULL) - timeStamp) > HOLDTIME)) // Long Hold
  {
    timeStamp = time(NULL);
    state = newValue; 
    // ((Button*)this)->Button::onLongHold(); 
  }
  else if(
    newValue != state && 
    state == BP_LOW) // Falling edge
  {      
    timeStamp = time(NULL);
    state = newValue;
    TempCtrl.(*((Button*)this)->Button::onFallingEdge());
    //onFallingEdge();
  }  
}   
    
uint8_t Button::getGpio() const
{   
  return gpio; 
}  

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)