我试图在函数参数中使用指针来读取类中的变量,如下所示:
void Function(int (*Argument)) {
Variable = Object*Argument.ClassVariable;
}
注意:我想这样做的原因是,在允许用户更改该类变量值之前,我可以将旋转编码器位置的值设置为等于类变量之前的值。 。这样,当用户循环通过类变量来设置它们时,每个变量的起始位置就是保存的值。
类对象名为Object1
,Object2
等。
我想从每个对象读取的变量名为ClassVariable
。
当我调用该函数时,我将使用Function(ClassNumber);
如果在调用该函数时ClassNumber
为13
,我希望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 )]);
}
答案 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