|
|
raddevus wrote: I'm not sure. What is a virtual function? Well that's a big topic (but what you remember is in the right direction). See, for instance Virtual Function in C++ - GeeksforGeeks[^].
Roughly speaking, you have a base button class and then some derived classes. The base class declares (and possibly define) the handler method. The derived classes, in turn provide their own implementation of the same method. A call to p->handler() at runtime resolves to the proper call to the actual derived class object.
Quote: Can you create a virtual function in Arduino code? Well, is C++ code, after all.
"In testa che avete, Signor di Ceprano?"
-- Rigoletto
|
|
|
|
|
A virtual function is a function that can be overloaded by a derived class.
In C# you mark such a function as virtual, IIRC - same as you do in C++.
To err is human. Fortune favors the monsters.
|
|
|
|
|
raddevus wrote: What do you think?
If we wouldn't be in the lounge where programming topics are off-limits, I'd call your solution sub-optimal: waiting 5 ms or more for each button, on a non-preemptive system like Arduino, is just asking for trouble. My favorite debouncing solution is a loop that reads all buttons and feeds them to software shift registers. When a shift register is filled with the same value, button is debounced.
But, as I said, here in the lounge I'll just keep my big mouth shut
Mircea
|
|
|
|
|
If I were to respond to your message, which I won't, I would say something along hte lines of:
1. Programmers and the like are the most abysmal people of all. They cannot enjoy any solution other than the ones they understand.
2. The OP asked for code samples which they found useful -- and I replied with code I found useful and interesting -- but never intimated that it was the _best_ solution. I am a hobbyist on Arduino. Nothing more.
3. It is comments exactly like yours that make the internet such an abysmal experience for everyone.
4. And I thought of another -- the debounce code that you don't like was actually taken from Jeremy Blum's fantastic book, Exploring Arduino[^]. So take it up with him. See his github and do a code review on him there (GitHub - sciguy14/Exploring-Arduino-2nd-Edition: Companion Code for the Second Edition of "Exploring Arduino," the book by Jeremy Blum[^]).
But I will not respond here. 
modified 8-Jan-23 17:19pm.
|
|
|
|
|
I sincerely apologize if my post rubbed you the wrong way. My old boss once said that I have the same level of empathy as Catbert, the evil HR director.
To make amends, here is a good post about debouncing that I've perused for many years: Debounce Code – One Post To Rule Them All | Hackaday[^]
Mircea
|
|
|
|
|
Thanks, that was very nice and I accept your apology.
I will take a look at the post. I honestly was offering the original code just as an interesting thing.
I was probably triggered by your post because I started out in IT back in '91 and since then it has always been a "my code is better than yours" pissing war with Devs.
I started out in Tech Support and knew I was a slug in the IT world.
Worked my way into QA and was there for 5 years or so and remember when this Dilbert came out[^].
Oh, it's funny now.
I finally made worked my way into Dev and have been here for about 22 years but I find that Devs are (and have always been) so competitive and are "always right". it just kind of triggers me.
When I was in QA if a dev ticked me off, I would just test his code, find a critical bug and then post it Friday afternoon. 
|
|
|
|
|
raddevus wrote: When I was in QA if a dev ticked me off, I would just test his code, find a critical bug and then post it Friday afternoon.
That is evil.
I love it 
|
|
|
|
|
Viewing this as a old C programmer, it all makes sense, is quite clear and does the job.
C++ version seems to introduce fuzziness and obfuscation (although straight C can do the same thing).
Cute or clever does not always = maintainable code.
Just saying.
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|
raddevus wrote: What do you think? I think this "belongs" on one of the technical forums ... but, given the general neglect of many forums, and the free-for-all the Lounge has become, I am just "blowing smoke"
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
|
|
|
|
|
|
Cut and Paste?
Sorry it's Sunday and I couldn't resist.
PartsBin an Electronics Part Organizer - An updated version available!
JaxCoder.com
|
|
|
|
|
Well, in C# I have a whole bunch of extension methods to make life easier for string manipulation, looping, matching, assertions, encoding/decoding, etc. I guess that's not exactly a coding trick, more of a re-usable library. And the only "discomfort" is that C# newbies think these things are built-in classes and methods on their respective data types.
|
|
|
|
|
I have one I just made the other day in C# for reading and writing structs over a serial port using marshalling. WriteStruct and ReadStruct on a SerialPort class. =)
It doesn't make *me* uncomfortable, but people might puke at the idea of using marshalling for sending data over serial rather than using something like binary serialization.
Marshalling requires less code. I'm nothing if not lazy.
To err is human. Fortune favors the monsters.
|
|
|
|
|
honey the codewitch wrote: Template-instance statics I've done that for cases where I didn't want to pass around a singleton instance:
class API
{
public:
static void DoThing();
private:
API();
static API *_This;
};
API *API::_This = NULL;
void API::DoThing()
{
if (_This == NULL) _This = new API();
} It's useful for create-only-if-needed scenarios. For us, those arise fairly often adapting to different hardware. They're also useful when the creation process is expensive or time-consuming.
In C++ I like the idea that API::DoThing() is a blatant syntax for a singleton concept.
I've also had cases where the public static functions define the 'API' for a collection, while the instance members and values are the elements in the collection.
Now, I know that singletons are a 'code smell', but trust me... I know what I'm doing.
Software Zen: delete this;
|
|
|
|
|
I totally get what you're saying. Just for clarity though template-instance statics add another dimension to statics because they are not shared between different instantiations of the same template.
template<int A> struct foo final {
static int value;
};
...
...
foo<1>::value = 5;
foo<2>::value = 4;
printf("%d + %d = %d\n",foo<1>::value,foo<2>::value,foo<1>::value+foo<2>::value);
To err is human. Fortune favors the monsters.
|
|
|
|
|
Congratulations, your Witch-ness! You have successfully taught an Old Dog a wonderful new trick!
Software Zen: delete this;
|
|
|
|
|
I didn't tell you the downside. You must initialize the statics to avoid a linker error, and I don't know about C++20 but previous versions require declarations like this for statics:
template <uint8_t Pin, uint32_t DebounceMS , bool OpenHigh, size_t Events>
int_button<Pin, DebounceMS, OpenHigh, Events>*
int_button<Pin, DebounceMS, OpenHigh, Events>::m_this = nullptr;
To err is human. Fortune favors the monsters.
|
|
|
|
|
I don't think that's a downside, really. I'd expect that to be required initialization, since non-template static members require it.
Software Zen: delete this;
|
|
|
|
|
I'm referring to the nasty syntax required.
To err is human. Fortune favors the monsters.
|
|
|
|
|
Maybe the "Named parameter idiom"[^]. Instead of:
Rectangle r(10, 15, 24, 42);
you can write:
Rectangle r;
r.left(10).top(15).width(24).height(42); Makes a world of difference when you have complicated objects with lots of parameters.
Mircea
|
|
|
|
|
yikes!
I've done similar, but mostly for constructing Abstract Syntax Trees.
To err is human. Fortune favors the monsters.
|
|
|
|
|
|
In C:
a^=b^=a^=b;
...will swap the values of a and b by XORing them a couple of times, assuming a and b are the same size. Works for large data structures just as well as for ints: quite fast, too. Back in the days before proper video cards, this was good for swapping in entire screen contents, or faking sprites or whatever...
Note that this doesn't work in C#: you have to go...:
a^=b;
b^=a;
a^=b;
...because unlike C, C# uses the original values of the variables throughout the evaluation of the expression, so what happens if you try to run the original statement is that one variable receives the swap, but the other one is garbage. And really, it only works for ints. But it does let you swap the variables without using a third one.
|
|
|
|
|
Use Background worker report progress to trigger different conditions on the main thread.
*** Ya Ya I know..background workers But I didn't architect the project
Private Sub Go(myList as list(of String))
bgw1.RunWorkerAsync(me,myList)
End Sub
Private Sub bgw1_DoWork(sender As Object, e As DoWorkEventArgs) Handles bgw1.DoWork
Dim myList As List(Of String) = e.Argument
Dim listCount As Integer = myList.Count
For i As Integer = 0 To listCount
Dim resultInteger = DoWork(myList(i))
bgw1.ReportProgress(resultInteger,myList(i))
Next
End Sub
Private Sub bgw1_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles bgw1.ProgressChanged
Dim p As Integer = e.ProgressPercentage
Dim s As String = CStr(e.UserState)
Select Case P
Case 1
lbl1.Text = s
Case 2
lbl2.Text = s
Case Else
lbl1.Text = "Invalid Result for " & s
lbl2.Text = "Invalid Result for " & s
End Select
End Sub
modified 10-Jan-23 11:06am.
|
|
|
|