So I'm fairly new at this, and am experimenting with classes as a way of working around delay(), but the compiler reads the following error expected unqualified-id before '{' token and shows the error happening at the location where I declare my function, i.e., void testFunction(){}
My ultimate intent is to create an object that will function as a watchclock in order to run another block of code (testFunction) every so often. I wish to store testFunction outside of any loops so that it has a global scope. But when I call this function from within the Mytimer class, it won't compile.
For reference, I've been using the adafruit website as a guide. The difference between that code and mine is I wish to replace the lines of code with a function call. But I didn't find anything useful searching the forums, so any help is much appreciated
here's my full code.
#define dispTimeTemp();
#define testFunction();
class Mytimer {
unsigned long preMillis; //referent time to check curMillis against
unsigned long curMillis; //
unsigned long timePassed = curMillis - preMillis;
unsigned long setDelay;
public: //initialize all variables declared in class
Mytimer(int tempdelay) { //receives one argument upon initialization to set the expected delay
curMillis = millis();
preMillis = curMillis;
setDelay = tempdelay;
timePassed = curMillis - preMillis;
}
void Update() {
timePassed = millis() - preMillis;
if (setDelay < timePassed) {
preMillis = millis();
testFunction();
}
}
};
Mytimer object1(1000);
void setup () {
}
void loop () {
object1.Update();
}
void testFunction() {
Serial.print("test function ran");
}
}
Besides supplying proper function prototypes, there's no good reason for calling the global function from inside your class. That causes too much loss of flexibility. You should supply your class constructor with a pointer to the function. That makes it much more general:
void testFunction1();
void testFunction2();
class Mytimer {
private:
unsigned long preMillis; //referent time to check curMillis against
unsigned long curMillis; //
unsigned long timePassed = curMillis - preMillis;
unsigned long setDelay;
void (*functPtr)();
public: //initialize all variables declared in class
Mytimer(int tempdelay, void (*ptr)()) {
curMillis = millis();
preMillis = curMillis;
setDelay = tempdelay;
timePassed = curMillis - preMillis;
functPtr = ptr;
}
void Update() {
timePassed = millis() - preMillis;
if (setDelay < timePassed) {
preMillis = millis();
functPtr();
}
}
};
Mytimer object1(1000, testFunction1);
Mytimer object2(500, testFunction2);
void setup () {
}
void loop () {
object1.Update();
object2.Update();
}
void testFunction1() {
Serial.print("test function 1 ran");
}
void testFunction2() {
Serial.print("test function 2 ran");
}
LightuC:
Don't use define to declare functions. Instead use
void testFunction ();
During my guess-and-checking with the code, I thought I remembered something about a sketch needing to reference functions earlier in the script than when they are actually used (or something like that). This was an attempt to do that, but I may be mixing up concepts. So feel free to let me know if my very application is wrong!
gfvalvo:
Besides supplying proper function prototypes, there's no good reason for calling the global function from inside your class. That causes too much loss of flexibility. You should supply your class constructor with a pointer to the function. That makes it much more general:
void testFunction1();
void testFunction2();
class Mytimer {
private:
unsigned long preMillis; //referent time to check curMillis against
unsigned long curMillis; //
unsigned long timePassed = curMillis - preMillis;
unsigned long setDelay;
void (*functPtr)();
void testFunction1() {
Serial.print("test function 1 ran");
}
void testFunction2() {
Serial.print("test function 2 ran");
}
WOW! Thanks for that. There's a lot for me to digest here. Would you mind elaborating on this concept?:
[calling the global function from inside your class] causes too much loss of flexibility. You should supply your class constructor with a pointer to the function. That makes it much more general:
It's called function pointers. Just like you can pass variable (references) to a method, you can also pass functions (references). And just like variables you can save that to use it later. And in case of a function reference, most logical way of using it would be to call it
rooshio:
During my guess-and-checking with the code, I thought I remembered something about a sketch needing to reference functions earlier in the script than when they are actually used (or something like that). This was an attempt to do that, but I may be mixing up concepts. So feel free to let me know if my very application is wrong!
Yes, you can't declare a function with a define statement.
// Replace these two lines:
#define dispTimeTemp();
#define testFunction();
// with these two lines:
void dispTimeTemp();
void testFunction();
This is, because the #define statement is processed by the preprocessor, which runs before the compiler. It is true, that you need to declare (or define) your function, before you call it. When your compiler analysis the code, it will see a call to an unknown function. How should it resolve that otherwise?
gfvalvo:
Besides supplying proper function prototypes, there's no good reason for calling the global function from inside your class. That causes too much loss of flexibility. [...]
This is true. However, passing a function pointer isn't either. It depends on the usage of the testFunction. In your original code, the method is only invoked in your Mytimer class, so make it a (private) method of that class.
This gives much cleaner code and you don't run into the problem of checking the function pointer. If, for example, you would pass a null pointer to your class, upon calling the function pointer the arduino will soft-reset itself (call to 0x0000). If you have the bootloader enabled and the vector table is relocated to your boot sector, the arduino might as well crash with undefined behaviour (because there might be nonsense at 0x0000).
Callbacks are an exception, but you need to check them properly.
LightuC:
Callbacks are an exception, but you need to check them properly.
Since the OP was implementing a "timer" class, I made the reasonable assumption that he / she wanted to do "something" on a periodic basis as determined by the timer. Doesn't make much sense to hard code in that "something" as a private method. If you do this, you might as well make the whole class static as you would only ever be able to use one instance anyway. So, in fact, this is a callback application. The code I post was a skeletal example of the technique. Any proper implementation would check for the callback pointer being null.
The other option would be to make it an abstract class with the called function being a pure virtual method. Then you could inherit this interface into new classes that implement custom functions. Didn't think the OP was there yet ……
gfvalvo:
Since the OP was implementing a "timer" class, I made the reasonable assumption that he / she wanted to do "something" on a periodic basis as determined by the timer. Doesn't make much sense to hard code in that "something" as a private method. If you do this, you might as well make the whole class static as you would only ever be able to use one instance anyway. So, in fact, this is a callback application. The code I post was a skeletal example of the technique. Any proper implementation would check for the callback pointer being null.
You are right, of course. But who knows, what the class is supposed to do and I felt like at least mentioning it. That is also why I mentioned the dependence on the use of the testFunction.
gfvalvo:
The other option would be to make it an abstract class with the called function being a pure virtual method. Then you could inherit this interface into new classes that implement custom functions. Didn't think the OP was there yet ……
An option I wouldn't recommend on the arduino. However, this would be the prefered way on any other system with more memory.
LightuC:
An option I wouldn't recommend on the arduino. However, this would be the prefered way on any other system with more memory.
I don't see how inheriting from an abstract class would be any more memory-intensive than defining the class from the ground up and implementing the same interface. Please elaborate.
gfvalvo:
I don't see how inheriting from an abstract class would be any more memory-intensive than defining the class from the ground up and implementing the same interface. Please elaborate.
Because when you use virtual functions, the compiler will have to generate a virtual table for every class that uses virtual functions. This can be quite some overhead both memory and performance wise. Of course, this always depends on the use case, but within a timer class I suspect performance should be good to avoid big overheads.