This is a simplified version of the library, but it is enough to show the problem i'm having. Whats weird is this library was working then suddenly it wasn't and I have no idea why because the crap the compiler is complaining about hasn't changed so I don't know what's going on.
Basically when I use this library, the compiler points to the line that has
resetTimer = rst;
and says
undefined reference to `PlayTime::resetTimer'
But if I declare the resetTimer variable as not static, then it complains about this line
bool isDone(bool reset = resetTimer);
Saying
invalid use of non-static data member 'PlayTime::resetTimer'
1.) use #pragma once instead of include guards
2.) use both header and cpp files for libraries - it actually makes them easier to read and edit. Example library
This compiles for me:
.h
#pragma once
#include "Arduino.h"
const bool RESET = true;
const bool NORESET = false;
class PlayTime
{
public:
PlayTime(bool rst, unsigned long time, bool microz);
void isDone();
private:
bool resetTimer;
};
Note that #pragma once is well supported across compilers but not actually part of the standard. Preprocessor get your intent better with this and you don’t need to worry about conflicting #define names and preprocessing is supposed to be faster.
That being said There has been heated debates about name space and this pragma because If your #include search path is sufficiently complicated, the compiler may be unable to tell the difference between two headers with the same basename (e.g. a/foo.h and b/foo.h) and a #pragma once in one of them will suppress both. Of course having two .h with the same name is calling for trouble ...
GCC automatically detects include guards in header files, and if there is one it treats the file as though it had #pragma once
Some people recommend doing
#ifndef FOO_H
#define FOO_H
#pragma once
// ...
#endif
I don’t use it until it becomes part of the standard, never bog me down... but most arduino projects are simple enough to not fall under the complex situations where the pragma might fail, so....
Thank you for taking the time to look at this... see what I want to accomplish, is having that resetTimer variable settable when the library is instantiated, but the subsequent functions should have the OPTION of overriding that setting. So in this example, the isDone() method needs an optional variable bool that will let me either omit it entirely which it would then leave resetTimer at the value it was set to when the library was invoked, OR I could include a true or false when calling isDone to override the initial setting.
I'll play with this and see if I can make it work.
OK, here's where Im at now ... the error im getting is:
undefined reference to `PlayTime::resetTimer'
It's choking on the setting of that static variable in the .cpp file and if I don't declare that variable as static in .h, then I cannot use it as the default value in the optional bool for any method declaration.
Here is .h
#ifndef PlayTime_h
#define PlayTime_h
#pragma once
#include "Arduino.h"
class PlayTime {
// bool static PlayTime::resetTimer;
public:
PlayTime(bool rst = true, unsigned long time = 100, bool microz = false);
private:
bool static resetTimer;
};
#endif
and .cpp
#include <Arduino.h>
#include <PlayTime.h>
PlayTime::PlayTime(bool rst, unsigned long time, bool microz)
{
resetTimer = rst;
}
I think what is interesting about this problem, is that I am required to declare the variable as static before I can use it as the default value of an optional method argument. I always saw statics as being unique to methods and never something that you would use on a class global variable, because any global variables would technically be static to that class by nature... at least in their behavior anyways. Unless there is something about method declaration that is not technically within the scope of the class its being declared in ... and I wouldn't know how to say that technically, but maybe there is something unique about the "outer" structure of a method whereas the method code itself is on the same level as all other methods such that a global variable keeps its value for all methods ... but when you need to use a class global variable inside of a method declaration ... perhaps its not really in the same "scope" as the code within the method ... I don't know ... just thinking out loud I suppose.
... But if that WERE the case, then it would explain why the methods in the .cpp can't access that variable ... but there HAS TO BE A WAY to do what I want to do ... which is to set a class global variable during class instantiation, then use that variable as the value for an optional method argument so that the programmer can override it.
I just thought of something... perhaps a way around this would be to simply make the optional argument always true then inside the method, I would compare it to the resetTimer variable and then determine if the user is overriding that setting or not ... seems like a klunky way to go about it, but it just might work in this situation.
never mind, if the variables oppose each other there really is no way to know if the user is trying to override or not - oh well.
I think what I'm going to do is change that variable into an INT then use two constants RESET and NORESET that the user can tap when needed, set those to 1 and 2 then pass 0 as the default and if it comes into the method as 0, then reference the value set during instantiation or if not 0, then use what the user passed.
Something I did find interesting about that, is that my IDE (CLion) when it corrected the static problem, it put the word static after bool where as I would have put it before bool ... but the error I get in this situation is the same either way ... but it does beg the question, what's the difference if you put the word before or after the datatype declaration?
And in case you were going to ask, I write my code in CLion because being able to type in the name of an object and hit '.' then get an instant drop down of every method associated with that object has changed my life with writing Arduino code... but when I compile and upload I always copy and paste over to the Arduino IDE because doing that successfully in CLion has typically been a hit and miss adventure so I got tired of wrestling with it and always use Arduino IDE for that part of the process.
Power_Broker:
This is odd. What you just posted compiles perfectly for me.
What board are you using? Maybe you have some odd compiler settings? Maybe a bad bootloader? Strange...
Its a nano ...
I did rip a lot of code out of the library to keep this discussion simple... but all I took out were all the methods and a few other class level variables... What I did include is the exact code that the compiler is choking on.
Member variables of a class made static are shared by all objects/instances of the class. So it’s technically like a global variable with its scope limited to the class. It’s basically what is called a class variable.
J-M-L:
Member variables of a class made static are shared by all objects/instances of the class. So it’s technically like a global variable with its scope limited to the class. It’s basically what is called a class variable.
In Java, I call them global variables... coming from the Java world, I don't much like C ... seems too ... picky and unnecessarily rigid.
Global variables are something else - as you Program here in C/C++ better drop the Java habits
I always hated the code once debug everywhere nature of java
(Yes it’s somewhat a different world and given the target architecture and limitations C/C++ is a better choice)
That might actually explain a lot. You might need to use the old bootloader version of the nano compiler (if you have that option). I have to do that for all my nanos.
Try compiling for a Mega and see if you get better results. If so, it's your nano compiler.
Power_Broker:
That might actually explain a lot. You might need to use the old bootloader version of the nano compiler (if you have that option). I have to do that for all my nanos.
Try compiling for a Mega and see if you get better results. If so, it's your nano compiler.
I use the USBASP programmer when I get Nano's and I flash them to the latest firmware ... no sense in uploading sketches at 57.6 when you can do it at 115.2 ... and this problem I'm having fails when I just do a compile check ... im not even trying to upload I always make sure my sketches compile before I upload.
J-M-L:
Global variables are something else - as you Program here in C/C++ better drop the Java habits
I always hated the code once debug everywhere nature of java
(Yes it’s somewhat a different world and given the target architecture and limitations C/C++ is a better choice)
I've been trying for a while to learn how to love C ... but ... it's just so rigid and it's not all that natural of a language ... Ive tried to master the switch away from the String class and use char arrays and byte arrays and the various methods that go with that ... and I just haven't been successful yet ... then there are the weird &'s and *'s that mean different things depending on what side of a word they're on ... its a whole different world and I probably would have eased into it better ifI had some kind of a "C for Java people" type tutorial ... cause for me ... learning and navigating C has been a lot like eating a week old bagel ... that I really should be using as a hokey puck ... but I'm out of Bagels so Ive got to try and get this one down without chipping a tooth ...
Yeah it’s easier the other way around as it’s always easy to take bad habits
Joke aside - java has been invented to be an abstraction above any hardware (hence the JVM and then JIT) whereas C was to make programming easier whilst being close to the hardware bits and bytes. No surprise then to feel it’s hard to move from the higher level of abstraction down.
understanding C is best if you understand the fundamental architecture of computer the way they were a few decades ago (which is somewhat close to what an Arduino is). Then the rigidity, the & and * etc all start to make sense.
Once you get that, if you understand OOP from your java experience - moving into C++ is not that hard.
As everything, one needs to practice and go slowly until concepts are well mastered, it’s not about moving from java to C it’s really starting almost fresh.
EasyGoing1:
I use the USBASP programmer when I get Nano's and I flash them to the latest firmware ... no sense in uploading sketches at 57.6 when you can do it at 115.2 ... and this problem I'm having fails when I just do a compile check ... im not even trying to upload I always make sure my sketches compile before I upload.
...bbbut... selecting different processors changes how it's compiled - at least I'm pretty sure. BLUF: If it compiles for me and not for you, it's because of your IDE/compiler settings I'm sure. Maybe it's not your processor selection, but probably something else.
J-M-L:
Yeah it’s easier the other way around as it’s always easy to take bad habits
Joke aside - java has been invented to be an abstraction above any hardware (hence the JVM and then JIT) whereas C was to make programming easier whilst being close to the hardware bits and bytes. No surprise then to feel it’s hard to move from the higher level of abstraction down.
understanding C is best if you understand the fundamental architecture of computer the way they were a few decades ago (which is somewhat close to what an Arduino is). Then the rigidity, the & and * etc all start to make sense.
Once you get that, if you understand OOP from your java experience - moving into C++ is not that hard.
As everything, one needs to practice and go slowly until concepts are well mastered, it’s not about moving from java to C it’s really starting almost fresh.
So when you said that getting back to the roots of how computers WERE a few decades ago ... resonates with me ... my first computer was a Commodore 64 .... back in 1982 ... taught myself how to program in basic ... and when I graduated to a C=128, I even learned how to save data directly into sectors of a floppy disk, which I used when I was 16 as kind of an ad hoc database that I used to record the specifics of my Mc Donalds pay check stubs ... just because I could ... lol ... of course back then I don't think SQL existed or it was just being created ... I didn't get my first PC until roughly 1992 ... but when I took electronics, part of those courses was microcontrollers which we had to code with machine language ... but they were Motorola 6800's ...
So I completely get what you're saying how when you think at that level, the &'s and the *'s make more sense ... but what can I read that will help me make that connection??? I'd like to think I'm able to put all that together once I see it clearly explained ...
You assumed that C/C++ will be as easy as java. But now you learn that it's not the case. Now accept that your assumption is wrong. Learn from scratch. Now tell us what/how you would do something in Java and maybe we can translate to the equivalent. Who knows, maybe you are gonna be the first guy that writes a book for "Java to C"
EasyGoing1:
So I completely get what you're saying how when you think at that level, the &'s and the *'s make more sense ... but what can I read that will help me make that connection??? I'd like to think I'm able to put all that together once I see it clearly explained ...