使用指针将变量用作对类变量

时间:2018-04-18 22:41:59

标签: c++ arduino

我试图在函数参数中使用指针来读取类中的变量,如下所示:

void Function(int (*Argument)) {
    Variable = Object*Argument.ClassVariable;
}

注意:我想这样做的原因是,在允许用户更改该类变量值之前,我可以将旋转编码器位置的值设置为等于类变量之前的值。 。这样,当用户循环通过类变量来设置它们时,每个变量的起始位置就是保存的值。

类对象名为Object1Object2等。 我想从每个对象读取的变量名为ClassVariable。 当我调用该函数时,我将使用Function(ClassNumber);

如果在调用该函数时ClassNumber13,我希望Variable等于Object13.ClassVariable

这可能吗?

进一步信息:

整个班级都是公开的。

类对象的构造函数(注意,这是arduino,byte是8位无符号):

  Modes(byte hue, byte sat, byte val, int del, bool hROal, bool hset, bool sset, bool vset, bool dset) {
    hueVal = hue;
    satVal = sat;
    valVal = val;
    delVal = del;
    hueROallow = hROal;
    hSet = hset;
    sSet = sset;
    vSet = vset;
    dSet = dset;
  }

每个班级对象都是一个单独的模式'用户可以选择。我打算在函数中使用的Argument是'模式编号'目前已被选中。

完整代码(非常重要的工作)

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH1106.h>

const byte Button2 = 8;

const byte EncApin = 3;           // EncApin **MUST BE interrupt**
const byte EncBpin = 4;           // These are the three pins the encoder A/B & button are connected to
const byte EncButt = 2;           //

static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};   // array to set encoder H/L sequence
byte encVal;          // initialises reading from encoder

Adafruit_SH1106 display(0);   // Initialise display? (On SPI OLED screens this sets the MOSI/CLK/DC/RST/CS pins)


int displayVal; // to store the current output value for display
String displayMode;
byte mode = 1;              // set mode 0 at beginning
byte qtyModes = 3;          // set number of modes that may be selected here

byte setMode = 1;
byte qtySetModes = 4;       // set number of sub-modes for setting values

///// FUNCTION PROTOTYPES ///////// must be declared here to allow the class to use them
void EncReading(); 
void EncReadingRO();

////////////////////////////////////////////////////////
////////////// ******** CLASSES ********* //////////////
////////////////////////////////////////////////////////
class Modes {

  public:   // everything in the class below this will be available to the program outside of the class

  // Class Member Variables
  // These are initialized at startup
  byte hueVal;
  byte satVal;
  byte valVal;
  int delVal;
  bool hueROallow;
  bool hSet;
  bool sSet;
  bool vSet;
  bool dSet;

  byte CLdisplayVal;
  String displayDesc;

  // These maintain the current state
  unsigned long prevMillis;   // will store last time LED was updated

  // Constructor - creates a Mode & initializes the member variables and state
  // additional options for whether rollover of values allowed needed
  Modes(byte hue, byte sat, byte val, int del, bool hROal, bool hset, bool sset, bool vset, bool dset) {
    hueVal = hue;
    satVal = sat;
    valVal = val;
    delVal = del;
    hueROallow = hROal;
    hSet = hset;
    sSet = sset;
    vSet = vset;
    dSet = dset;
  }

  void Update() {
    switch (setMode) {
      case 1:           // case 1 for hue update
        if (hSet == 0) { 
          displayDesc = F(" HUE (FIXED)");
          CLdisplayVal = hueVal;
          break;
          }
        if (hueROallow == 1) EncReadingRO();
        else EncReading();
        hueVal = encVal;
        CLdisplayVal = encVal;
        displayDesc = F(" HUE");
        break;

      case 2:           // saturation update
        if (sSet == 0) { 
          displayDesc = F(" SATURATION (FIXED)");
          CLdisplayVal = satVal;
          break;
          }
        EncReading();
        satVal = encVal;
        CLdisplayVal = encVal;
        displayDesc = F(" SATURATION");
        break;

      case 3:           // value update
        if (vSet == 0) { 
          displayDesc = F(" BRIGHTNESS (FIXED)");
          CLdisplayVal = valVal;
          break;
          }
        EncReading();
        valVal = encVal;
        CLdisplayVal = encVal;
        displayDesc = F(" BRIGHTNESS");
        break;

      case 4:           // delay update
        if (dSet == 0) { 
          displayDesc = F(" TIMING (FIXED)");
          CLdisplayVal = delVal;
          break;
          }
        EncReading();
        delVal = encVal;
        CLdisplayVal = encVal;
        displayDesc = F(" TIMING");
        break;
      }
    displayReading();
  }

  void displayReading() {
    unsigned long currMillis = millis();        // These four lines are to
    static unsigned long prevMillis;                     // act as a delay, except
    if (currMillis - prevMillis >= 100) {   // without holding the execution          // note: encoder reading sensitive to delal changes, 100 not bad
      prevMillis = currMillis;                  // of other code
      display.fillRect(39, 30, 54, 24, BLACK);
      display.fillRect(0, 0, 128, 18, WHITE);
      display.setTextSize(1);
      display.setTextColor(BLACK);
      display.setCursor(1,1);
      display.println(displayMode);
      display.setCursor(1,10);
      display.println(displayDesc);
      display.setTextSize(3);
      display.setTextColor(WHITE);
      display.setCursor(39,30);
      display.println(CLdisplayVal);
      display.display();
    }
  }
};


////////// Construct objects - this sets up the objects we want of the class 'Modes'
// Modes modex(Hue0-255, Sat0-255, Val0-255, Del0-255, Hue rollover0/1, Hue settable0/1, Sset0/1, Vset0/1, Dse0/1
Modes mode1(50, 100, 150, 100, 1, 1, 1, 1, 1);   // object 'mode1', initializing with H50, S100, V150, D100, hue rollover & settable options ON
Modes mode2(55, 105, 155, 105, 0, 1, 1, 1, 1);
Modes mode3(63, 73, 83, 93, 0, 1, 1, 1, 1);

////////////////////////////////////////////////////////
////////// ******** SETUP / LOOP ********* /////////////
////////////////////////////////////////////////////////

void setup() {
  Serial.begin(115200);
  display.begin(SH1106_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3D (for the 128x64)
  display.clearDisplay();
  display.display();
  pinMode(EncApin, INPUT_PULLUP);  // Turn on internal pullup resistors for encoder pins & buttons
  pinMode(EncBpin, INPUT_PULLUP);
  pinMode(Button2, INPUT_PULLUP);
  pinMode(EncButt, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(EncApin), read_encoder, CHANGE);
  attachInterrupt(digitalPinToInterrupt(EncButt), encButtPress, FALLING);
  pciSetup(Button2);    // set up encApin for pin change interrupt
  encVal = mode1.hueVal;           // initialize the encoder to the mode1 setmode1 value
}

void loop() {
  switch(mode) {
    case 1:
      displayMode = F("MODE:Call it anything");
      mode1.Update();
      // add call to the mode 1 LED display function here, using mode1.xyz variables
      break;

    case 2:
      displayMode = F("MODE:Second");
      mode2.Update();
      // add call to the mode 2 LED display function here, using mode2.xyz variables
      break;

    case 3:
      displayMode = F("MODE:Third");
      mode3.Update();
      // add call to the mode 2 LED display function here, using mode2.xyz variables
      break;

  }

Serial.print(F("Enc: "));
Serial.print(encVal);
Serial.print(F("    M1 H: "));
Serial.print(mode1.hueVal);
Serial.print(F("  S: "));
Serial.print(mode1.satVal);
Serial.print(F("  V: "));
Serial.print(mode1.valVal);
Serial.print(F("  D: "));
Serial.print(mode1.delVal);
Serial.print(F("    M2 H: "));
Serial.print(mode2.hueVal);
Serial.print(F("  S: "));
Serial.print(mode2.satVal);
Serial.print(F("  V: "));
Serial.print(mode2.valVal);
Serial.print(F("  D: "));
Serial.println(mode2.delVal);

//  Serial.print(F("freeMemory()="));
//  Serial.println(freeMemory());

}

////////////////////////////////////////////////////////
//////////// ******** FUNCTIONS ********* //////////////
////////////////////////////////////////////////////////

///// Function to set encVal, 0-255, NO rollover
void EncReading() {
  int8_t encoderdata;
  encoderdata = read_encoder();                           // returns the +- value from the read_encoder function
  if (encoderdata) {                                      // if not equal to zero
    if (encVal+encoderdata>255 || encVal+encoderdata<0);    // these if/else statements clamp encVal to prevent byte rollover
    else {
      encVal += encoderdata;
    } // end else
  }
}
///// Function to set encVal, 0-255, WITH rollover
void EncReadingRO() {
  int8_t encoderdata;
  encoderdata = read_encoder();                           // returns the +- value from the read_encoder function
  if (encoderdata) {                                      // if not equal to zero
    encVal += encoderdata;
  }
}

////////////////////////////////////////////////////////
//////////// ******** INTERRUPTS ********* /////////////
////////////////////////////////////////////////////////

/////// Pin Change Interrupt Setup Function /////////// called in void setup to set the selected pin as a PCI
void pciSetup(byte pin)
{
    *digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin));  // enable pin
    PCIFR  |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
    PCICR  |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group
}

//////////// PCI Interrupt Sub Routines////////
// ISR (PCINT0_vect) is ISR for D8-13 // ISR (PCINT2_vect) is ISR for A0-5 // ISR (PCINT2_vect) is ISR for D0-7 //
ISR (PCINT0_vect) // handle pin change interrupt for D8 to D13 here, depending on which are set in void setup
 {    
  if(digitalRead(Button2) == LOW)
     buttonPress();
 }


//////// Func for ENCODER button press ISR ****** CHANGE 'setMode' ***** ///////////////
void encButtPress() {
  static unsigned long prevInterrTime = 0;
  unsigned long interrTime = millis();
  if (interrTime - prevInterrTime > 200) {
    setMode++;
    // *** ADD HERE *** need to set encVal to whatever the existing value is in the setMode being switched to
    if (setMode > qtySetModes) setMode = 1;
    prevInterrTime = interrTime;
    setPrevEncVal(mode);
  }
}

void setPrevEncVal(byte (*modeNum)) {
  switch (setMode) {
    case 1: encVal = mode&modeNum.hueVal; break;
    case 2: encVal = mode1.satVal; break;
    case 3: encVal = mode1.valVal; break;
    case 4: encVal = mode1.delVal; break;
  }
}

//////// Func for button press ISR ****** CHANGE 'mode' ***** ///////////////
void buttonPress() {
  static unsigned long prevInterrTime = 0;
  unsigned long interrTime = millis();
  if (interrTime - prevInterrTime > 200) {
    mode++;           // increment 'mode'
    setMode = 1;      // reset 'setMode'
  }
  if (mode > qtyModes) mode = 1;
  prevInterrTime = interrTime;
}

//////// Func for +1/-1 encoder reading ISR ///////
/* returns change in encoder state (-1,0,1) */
int8_t read_encoder() {
  static uint8_t old_AB = 0;
  old_AB <<= 2;
  old_AB |= ((digitalRead(EncBpin))?(1<<1):0) | ((digitalRead(EncApin))?(1<<0):0);
  return ( enc_states[( old_AB & 0x0f )]);
}

1 个答案:

答案 0 :(得分:1)

回答这个问题:

你不能,因为C ++是一种编译语言,因此,函数,对象和变量的名称变得毫无意义(相反,它们只是地址)

例如,您可以在代码中看到

 int myVariable = 6;

但编译器看到:

 mov [6], [0x6874]

阅读Compiled vs. Interpreted Languages以获取更多参考资料。

[针对您的具体情况]

如果你使用接口和工厂,你会更好。

class Mode {
    virtual int getAttribute() = 0;
}

class AMeaningfulName : public Mode {
    int getAttribute()  { return 1; }
}

class SelectAnotherMeaningfulNamePlease : public Mode {
    int getAttribute() { return 2; }
}

class ModeFactory {
    Mode getMode(int userSelectedMode) {

        if (userSelectedMode == MODE_1) {
            return new AMeaningfulMode();
        } else if (userSelectedMode == MODE_2) {
            return new SelectAnotherMeaningulNamePlease();
        } else {
            //send an exception so the user knows he selected something invalid
        }
    }
}


///now, in your main or elsewhere
ModeFactory factory = new ModeFactory();
Mode mode = factory.getMode(userSelectedValue);
int theAtttributeIWanted = mode.getAttribute();

看看虚拟功能 https://en.wikipedia.org/wiki/Virtual_function

还有工厂模式 https://www.tutorialspoint.com/design_pattern/factory_pattern.htm