Override a method when creating an object in Arduino/C++ - c++

I am working on a C++ Arduino sketch that creates a GUI on an OLED display. I want to have buttons buttons that all do different things when you press them. In Java, I can simply override the method when creating an anonymous class like this:
class Example {
public void method() {
}
}
Example e = new Example() {
#Override
public void method() {
//do something
}
};
So my question is: Can I do this in an C++?

As arduino sketch are in fact C/C++, you could do the same as in Java.
class Button {
virtual void push() = 0;
}
class PowerButton : public Button {
virtual void push() {
shutdown();
}
}
Notice the virtual keyword, it's used to declare a method overidable, the "= 0" means pure virtual (the address of the method is 0). It simply says that this method is not implemented in this class, the class became abstract as in Java.
Also, the virtual keyword is not mandatory, but if you don't put it, C++ will just call the method of the given type and not from the real type.
Take a look there
But, the difference with Java is that you can't create an anonymous class directly in the code. Instead, maybe take a look for lambda.
For example, the class Button would became :
class Button {
public:
Button(const std::function<void()> &pushCallback) :
mPushCallback(pushCallback) {}
void push() { mPushCallback(); }
private:
const std::function<void()> mPushCallback;
And then the usage:
Button powerButton([]() {
powerOff();
});
Brackets are use to "capture" a variable, for example this, &str { myMethodInMyClass(str); }
Parenthesis are used to pass parameters
The std::function class take the function type as type parameter, a function that take a string as const ref and an int and that return an int will look like this : std::function<int(const std::string &, int)>

Related

Preferred way to understand object type at runtime

Consider I have a Plant class that has derived Fruit and Vegetable classes, and Fruit class has some more derived classes, like Orange and Apple, while Vegetable has derived Potato and Tomato. Assume, Plant has Plant::onConsume()=0; method:
class Plant
{
public:
virtual void onConsume(void)=0;
};
class Fruit:public Plant
{
};
class Orange:public Fruit
{
void onConsume(void)
{
// Do something specific here
}
};
class Apple:public Fruit
{
void onConsume(void)
{
// Do something specific here
}
};
class Vegetable:public Plant
{
};
class Potato:public Vegetable
{
void onConsume(void)
{
// Do something specific here
}
};
class Tomato:public Vegetable
{
void onConsume(void)
{
// Do something specific here
}
};
class Consumer
{
public:
void consume(Plant &p)
{
p.onConsume();
// Specific actions depending on actual p type here
// like send REST command to the remote host for Orange
// or draw a red square on the screen for Tomato
}
};
Suppose, I have a Consumer class with Consumer::consume(Plant) method. This "consume" method should perform different actions for different "Plants" instances/types, among calling Plant::onConsume() for any of "Plants". These action ain't directly related to the Plant class, require a lot of different additional actions and parameters, could literally be completely arbitrary, so cannot be implemented inside onConsume method.
What is the preferred method to implement this? As I understand, it is possible to implement some "Plant::getPlantType()=0" method, that would return plant type, but in this case I'm not sure what should it return. In case the returned value would be an enum, I'd need to change this enum each time I add a new derived class. And in any case, there's no control that multiple derived classes could return the same value.
Also, I'm aware there's a dynamic_cast conversion that returns nullptr if conversion could not be made, and typeid() operator that returns std::typeinfo (even with typeinfo::name()), which could be used in the switch() (it's just great for my case). But I'm afraid it could significally slow down the execution and make code heavier.
So, my question is, what is the preferred way in C++ to do that? maybe I just forgot about some simpler way to implement that?
A little update. Thank you for your explanations about inheritance, encapsulation etc! I supposed it's clear from my question, but it is not, I am sorry about that. So, please think about it, like I don't have an access to the whole Plant sources hierarchy, just need to implement this Consumer::onConsume(Plant). So I cannot add new specific methods in it. Or, also, it could be considered as a Plants library, that I have to write once, and make it usable for other devs. So, I could divide use cases/functionality into two parts: one that implemented "per class" in the Plant::onConsume() method, and second that is unknown yet and will differ depending on usage.
One option would be the visitor pattern, but this requires one function per type in some class. Basically you create a base class PlantVisitor with one Visit function per object type and pass add a virtual method to Plant that receives a PlantVisitor object and calls the corresponding function of the visitor passing itself as parameter:
class PlantVisitor
{
public:
virtual void Visit(Orange& orange) = 0;
virtual void Visit(Tomato& tomato) = 0;
...
};
class Plant
{
public:
virtual void Accept(PlantVisitor& visitor) = 0;
};
class Orange : public Plant
{
public:
void Accept(PlantVisitor& visitor) override
{
visitor.Visit(*this);
}
};
class Tomato : public Plant
{
public:
void Accept(PlantVisitor& visitor) override
{
visitor.Visit(*this);
}
};
This would allow you to do something like this:
class TypePrintVisitor : public PlantVisitor
{
public:
void Visit(Orange& orange) override
{
std::cout << "Orange\n";
}
void Visit(Tomato& tomato) override
{
std::cout << "Tomato\n";
}
};
std::vector<std::unique_ptr<Plant>> plants;
plants.emplace_back(std::make_unique<Orange>());
plants.emplace_back(std::make_unique<Tomato>());
TypePrintVisitor visitor;
for (size_t i = 0; i != plants.size(); ++i)
{
std::cout << "plant " << (i+1) << " is a ";
plants[i]->Accept(visitor);
}
Not sure the need for this does not indicate a design inefficiency though.
Btw: If you've got multiple visitors and do not necessarily want to implement logic for every single type in all of them, you could add default implementations in PlantVisitor that call the function for the supertype instead of specifying pure virtual functions.
Polymorphism is all about not having to know about a specific type. Usually your design is flawed if you discover having to detect a specific type explicitly.
At very first:
void Consumer::consume(Plant p)
does not work as intended! The Plant object is accepted by value, i. e. its bytes are copied one by one; however, only those of the Plant type, any others (those of derived types) are ignored and get lost within consume function – this is called object slicing.
Polymorphism only works with references or pointers.
Now assume you want to do something like the following (incomplete code!):
void Consumer::consume(Plant& p) // must be reference or pointer!
{
p.onConsume();
generalCode1();
if(/* p is apple */)
{
appleSpecific();
}
else if(/* p is orange */)
{
orangeSpecific();
}
generalCode2();
}
You don't want to decide yourself upon type, you let the Plant class do the stuff for you, which means you extend its interface appropriately:
class Plant
{
public:
virtual void onConsume() = 0;
virtual void specific() = 0;
};
The code of the consume function will now be changed to:
void Consumer::consume(Plant const& p) // must be reference or pointer!
{
p.onConsume();
generalCode1();
p.specific();
generalCode2();
}
You'll do so at any place you need specific behaviour (and specific is just a demo name, chose one that describes nicely what the function actually is intended to do).
p.onConsume();
generalCode1();
p.specific1();
generalCode2();
p.specific2();
generalCode3();
p.specific3();
generalCode4();
// ...
Of course you need now to provide appropriate implementations in your derived classes:
class Orange:public Fruit
{
void onConsume() override
{ }
void specific() override
{
orangeSpecific();
}
};
class Apple:public Fruit
{
void onConsume() override
{ }
void specific() override
{
appleSpecific();
}
};
Note the addition of override keyword, which protects you from accidentally creating overloaded functions instead actually overwriting in case of signature mismatch. It helps you, too, to locate all places of necessary changes if you discover having to change the function signature in the base class.

Virtual function pointer to a function in a derived class

I'm trying to see if the following is possible. I'm still on an old Visual Studio 2008 C++ compiler, so bear with me.
Say, I have two classes derived from a single class. Both have the same function that I want to pass as a pointer to be called from a static function.
Here's pseudocode:
class CDlg1 : public CDialog
{
virtual void func1(int v)
{
wprintf(L"CDlg1::func1 was called, v=%d\n", v);
}
void do_delayed_call()
{
delayed_call_func1(func1);
}
}
class CDlg2 : public CDialog
{
virtual void func1(int v)
{
wprintf(L"CDlg2::func1 was called, v=%d\n", v);
}
void do_delayed_call()
{
delayed_call_func1(func1);
}
}
static void delayed_call_func1(void* pfn)
{
//... some additional action
//int v = something
//Call pfn() after a delay
pfn(v);
}
I can't figure out, do I need to template for this function pointer?
It's hard to know what's going on without seeing code for CDialog. Is "func1" virtual in CDialog? If so, you can write:
void delayed_call_func1(CDialog& cdialog)
{
... ;
cdialog.func1(v);
}
If not, you could indeed use a template:
template <typename CDlgX>
void delayed_call_func1(CDlgX* p)
{
... ;
p->func1(v);
}
Or, if your old compiler can compile boost, there are several libraries therein such as boost::function that are similar to the C++11 std::function, and can be used to supply delayed_call_func1 with an arbitrary callback to your member function, but I'd suggest you only look into that after updating your compiler - then you can use lambdas too.

Calling functions implicitly from derived classes

In my main.cpp I have something similar to the following:
void OnEventStart(int id)
{
// Do some stuff
}
This function is a callback, it is only triggered (by the main sdk that this is from) when an event has occured.
I now have this class:
class SomeClass {
public:
void OnEventStart(int id);
};
void SomeClass::OnEventStart(int id)
{
// Do some other stuff
}
Now I want to trigger void SomeClass::OnEventStart(int id) without doing something like this:
SomeClass class;
void OnEventStart(int id)
{
// Do some stuff
class.OnEventStart(id);
// AnotherClass.OnEventStart(id);
// Another.OnEventStart(id);
}
As you can imagine, using a method like this can easily clutter up the inital function/callback.
Your question is not very clear, but I'll assume the following:
You have some sort of callback handler that takes a void(*)(int).
In that case, if SomeClass is stateless, you can simply use a lambda wrapper:
my_framework_callback([]{ SomeClass{}.OnEventStart(id); });
If I misunderstood what you were asking, here's a different assumption:
SomeClass and similar types are stateless.
You're annoyed by having to instantiate SomeClass just to call one of its methods.
If that's the case, you can create a temporary instance of SomeClass on the spot:
void OnEventStart(int id)
{
SomeClass{}.OnEventStart(id);
AnotherClass{}.OnEventStart(id);
Another{}.OnEventStart(id);
}
If your question is instead...
"I have various classes with the same interface, and I want to call a function on all of them."
...then one possible solution would be using an abstract base class that provides .OnEventStart() = 0 and store an std::vector of pointers to that base class.
std::vector<std::unique_ptr<MyAbstractClass>> handlers;
void OnEventStart(int id)
{
for(auto& h : handlers)
h->OnEventStart(id);
}

C++ an object with its own method?

I'm sorry, this is probably a stupid question. I am obviously misunderstanding something fundamental about object oriented programming. I am used to C and am now trying to use C++.
I have some buttons in a class called Button. Each button does something different. What I want to write is something like this:
Button button1;
Button button2;
...
void button1::onClick () {
...
}
void button2::onClick () {
...
}
But that does not work ("button 1 is not a class, namespace or enumeration" - yes I know!). I know I could just make a separate class for each button:
class button1_class : public Button {
public:
void onclick () {
...
}
} button1;
class button2_class : public Button {
...
}
But to me it 'feels' wrong to make a class when I know for sure it will only have one member.
I'm using Agui, a GUI library for Allegro 5.
EDIT
Thanks for the responses. While they are all helpful and (I think) all valid answers, nobody has actually said yet "no you cannot have an object with its own unique method because..."
So for example, if object1 is of type ObjectClass then object1 is not allowed to have a method (a member function) that is unique to object1, but rather possesses only the methods that are defined as part of ObjectClass. Is that right?
I'm sorry I did not include my actual use case. I was kind of more interested in just getting my head around OOP so that I can do it properly on my own.
EDIT2
Looking at the responses in more detail I suppose it is possible with lambda expressions, it's just not in the way I imagined it. Thanks again
The natural C++ way is to do as vsoftco explained, with virtuals and inheritance.
However, if your Button class has already everything needed, and the only thing that changes between the buttons is the unique (trhow-away) action to be performed, you may want to consider this alternative:
class Button {
function<void()> f;
public:
Button(function<void()> mf) : f(mf) {}
void onClick() { f(); }
};
This variant of your class uses a function object (think of it as a kind of function pointer but much more flexible to use).
You can then use it with lambda-functions as in this example:
int main(int ac, char**av)
{
Button button1([&]() { cout << "Hello 1!\n"; });
Button button2 ([]() { cout << "Hello 2!\n"; });
button1.onClick();
button2.onClick();
}
If the buttons have different functionalities, best thing to do is to create a BaseButton class in which you mark the onclick() as virtual (or make it pure virtual, which will make BaseButton an abstract class), then derive each other button from BaseButton, making sure to override onclick() in each derived class. You then need to use the buttons via a reference or pointer to a BaseButton, this way you achieve what is called "polymorphic behaviour".
For example:
class BaseButton
{
virtual void onclick() {/*implement here or declare pure virtual*/}
};
class RedButton: public BaseButton /* overrides only onclick */
{
void onclick() override { /*specific implementation for Red Buttons */}
};
class ShinyRedButton: public RedButton /* overrides only onclick */
{
void onclick() override { /*specific implementation for Shiny Red Buttons */}
};
then use it like (C++14 smart pointers)
std::unique_ptr<BaseButton> bb = new ShinyRedButton;
bb->onclick(); // will pick up the "right" ShinyRedButton::onclick()` function
You can do this in many ways.
Using a Button class where button objects have a pointer to methods that are invoked onClick. In C you would do this using a callback and you can also do it that way in C++:
class Button {
using funType = void(void);
public:
Button(funType* callback) : function(callback) { }
void onClick() { function(); }
private:
funType* function;
};
However do take note that function pointers are error prone, can't really be inlined by the compiler, and should generally be avoided. This method also works with capture-less lambdas.
Button red([] { std::cout << "Red button\n"; });
Button green(&green_button_function);
Creating different Button objects with different onClick methods on the fly. C++ has a mechanism to do this called templates:
template <class Fun>
class Button {
public:
Button(Fun f) : functor(f) { }
void onClick() { functor(); }
private:
Fun functor;
};
template <class Fun>
Button<Fun> make_button(Fun f) { return Button<Fun>(f); }
I am omitting details such as references on purpose here.
You could then use the Button class with callbacks as well as lambdas in the following way:
auto green = make_button([] { std::cout << "Green button pressed!\n"; });
auto red = make_button(&red_button_function);
You need to use auto with this method because otherwise you would have to specify the type of the functionality by hand, which is not possible e.g. for lambda objects.
Using polymorphism as shown by vsoftco, where you create separate classes for each Button functionality. Or you can make a ButtonAction abstract class to which Button has a reference. Then you implement different functionalities in different classes, but stay with one Button class. This is known as the strategy pattern:
class ButtonAction {
public:
virtual void onClick() = 0;
};
class Button {
public:
Button(std::unique_ptr<ButtonAction> action) :
action_(std::move(action)) {}
void onClick() { action_->onClick(); }
private:
std::unique_ptr<ButtonAction> action_;
};
class RedButtonAction : public ButtonAction {
void onClick() override { red(); }
};
class GreenButtonAction : public ButtonAction {
void onClick() override { green(); }
};
Using this method requires constructing Buttons from ButtonAction unique_ptrs
Button red(std::unique_ptr<ButtonAction>(new RedButtonAction));
Button green(std::unique_ptr<ButtonAction>(new GreenButtonAction));
You're right in that, if each button is fundamentally the same but needs different event handlers bound to it, implementing a new type for each one is not quite right.
Instead your Button type would have a member function that allows users to "attach" an event handler, and a member function to invoke it.
class Button
{
public:
Button()
: onClickHandler()
{}
void setOnClickHandler(std::function<void()> callback)
{
onClickHandler = callback;
}
friend class UI;
private:
void onClick()
{
onClickHandler();
}
std::function<void()> onClickHandler;
};
Then your user does:
void foo()
{
std::cout << "Some buttons do this!\n";
}
Button btn;
btn.setOnClickHandler(foo);
And your program's internals will set up things such that your window manager (above I've assumed that it's some class called UI) invokes btn.onClick() for you, which, since you "attached" foo, will end up invoking foo.
(In modern C++ you'd probably make use of lambda functions to tidy this up, but the above is a simple example to showcase the general design idea.)
In this way, you can attach different handlers to different Button instances, but the Button interface itself is stable.
This is similar to how, for example, you manipulate the DOM in JavaScript.
Using a std::function is the key here. You will have the virtual call overheard and potential memory allocation if your callable (lambda, function, member function) is large. This achieves your requirements of a single type executing different callbacks without defining an class inheritance. Also using uniform initialization makes it very convenient to construct Button class with a lambda without manually creating a constructor.
Live example:
http://coliru.stacked-crooked.com/a/f9007c3f103f3ffe
#include <functional>
#include <vector>
using namespace std;
struct Button
{
function<void()> OnClick;
};
int main()
{
vector<Button> buttons =
{
{[] { printf("Button0::OnClick()\n"); }},
{[] { printf("Button1::OnClick()\n"); }},
{[] { printf("Button2::OnClick()\n"); }},
};
for(auto&& button : buttons)
button.OnClick();
}
Your Agui library supports a signaling system, with the member function addActionListener.
This allows you to derive a class from agui::ActionListener to perform the specific task intended for one or more buttons:
class SimpleActionListener : public agui::ActionListener
{
public:
virtual void actionPerformed(const agui::ActionEvent &evt)
{
std::cout << "Button pushed" << std::endl;
}
};
The object above can be attached to a button's "press" action with:
SimpleActionListener simpleAL;
button1.addActionListener(&simpleAL);

oop - C++ - Proper way to implement type-specific behavior?

Let's say I have a parent class, Arbitrary, and two child classes, Foo and Bar. I'm trying to implement a function to insert any Arbitrary object into a database, however, since the child classes contain data specific to those classes, I need to perform slightly different operations depending on the type.
Coming into C++ from Java/C#, my first instinct was to have a function that takes the parent as the parameter use something like instanceof and some if statements to handle child-class-specific behavior.
Pseudocode:
void someClass(Arbitrary obj){
obj.doSomething(); //a member function from the parent class
//more operations based on parent class
if(obj instanceof Foo){
//do Foo specific stuff
}
if(obj instanceof Bar){
//do Bar specific stuff
}
}
However, after looking into how to implement this in C++, the general consensus seemed to be that this is poor design.
If you have to use instanceof, there is, in most cases, something wrong with your design. – mslot
I considered the possibility of overloading the function with each type, but that would seemingly lead to code duplication. And, I would still end up needing to handle the child-specific behavior in the parent class, so that wouldn't solve the problem anyway.
So, my question is, what's the better way of performing operations that where all parent and child classes should be accepted as input, but in which behavior is dictated by the object type?
First, you want to take your Arbitrary by pointer or reference, otherwise you will slice off the derived class. Next, sounds like a case of a virtual method.
void someClass(Arbitrary* obj) {
obj->insertIntoDB();
}
where:
class Arbitrary {
public:
virtual ~Arbitrary();
virtual void insertIntoDB() = 0;
};
So that the subclasses can provide specific overrides:
class Foo : public Arbitrary {
public:
void insertIntoDB() override
// ^^^ if C++11
{
// do Foo-specific insertion here
}
};
Now there might be some common functionality in this insertion between Foo and Bar... so you should put that as a protected method in Arbitrary. protected so that both Foo and Bar have access to it but someClass() doesn't.
In my opinion, if at any place you need to write
if( is_instance_of(Derived1) )
//do something
else if ( is_instance_of(Derived2) )
//do somthing else
...
then it's as sign of bad design. First and most straight forward issue is that of "Maintainence". You have to take care in case further derivation happens. However, sometimes it's necessary. for e.g if your all classes are part of some library. In other cases you should avoid this coding as far as possible.
Most often you can remove the need to check for specific instance by introducing some new classes in the hierarchy. For e.g :-
class BankAccount {};
class SavingAccount : public BankAccount { void creditInterest(); };
class CheckingAccount : public BankAccount { void creditInterest(): };
In this case, there seems to be a need for if/else statement to check for actual object as there is no corresponsing creditInterest() in BanAccount class. However, indroducing a new class could obviate the need for that checking.
class BankAccount {};
class InterestBearingAccount : public BankAccount { void creditInterest(): } {};
class SavingAccount : public InterestBearingAccount { void creditInterest(): };
class CheckingAccount : public InterestBearingAccount { void creditInterest(): };
The issue here is that this will arguably violate SOLID design principles, given that any extension in the number of mapped classes would require new branches in the if statement, otherwise the existing dispatch method will fail (it won't work with any subclass, just those it knows about).
What you are describing looks well suited to inheritance polymorphicism - each of Arbitrary (base), Foo and Bar can take on the concerns of its own fields.
There is likely to be some common database plumbing which can be DRY'd up the base method.
class Arbitrary { // Your base class
protected:
virtual void mapFields(DbCommand& dbCommand) {
// Map the base fields here
}
public:
void saveToDatabase() { // External caller invokes this on any subclass
openConnection();
DbCommand& command = createDbCommand();
mapFields(command); // Polymorphic call
executeDbTransaction(command);
}
}
class Foo : public Arbitrary {
protected: // Hide implementation external parties
virtual void mapFields(DbCommand& dbCommand) {
Arbitrary::mapFields();
// Map Foo specific fields here
}
}
class Bar : public Arbitrary {
protected:
virtual void mapFields(DbCommand& dbCommand) {
Arbitrary::mapFields();
// Map Bar specific fields here
}
}
If the base class, Arbitrary itself cannot exist in isolation, it should also be marked as abstract.
As StuartLC pointed out, the current design violates the SOLID principles. However, both his answer and Barry's answer has strong coupling with the database, which I do not like (should Arbitrary really need to know about the database?). I would suggest that you make some additional abstraction, and make the database operations independent of the the data types.
One possible implementation may be like:
class Arbitrary {
public:
virtual std::string serialize();
static Arbitrary* deserialize();
};
Your database-related would be like (please notice that the parameter form Arbitrary obj is wrong and can truncate the object):
void someMethod(const Arbitrary& obj)
{
// ...
db.insert(obj.serialize());
}
You can retrieve the string from the database later and deserialize into a suitable object.
So, my question is, what's the better way of performing operations
that where all parent and child classes should be accepted as input,
but in which behavior is dictated by the object type?
You can use Visitor pattern.
#include <iostream>
using namespace std;
class Arbitrary;
class Foo;
class Bar;
class ArbitraryVisitor
{
public:
virtual void visitParent(Arbitrary& m) {};
virtual void visitFoo(Foo& vm) {};
virtual void visitBar(Bar& vm) {};
};
class Arbitrary
{
public:
virtual void DoSomething()
{
cout<<"do Parent specific stuff"<<endl;
}
virtual void accept(ArbitraryVisitor& v)
{
v.visitParent(*this);
}
};
class Foo: public Arbitrary
{
public:
virtual void DoSomething()
{
cout<<"do Foo specific stuff"<<endl;
}
virtual void accept(ArbitraryVisitor& v)
{
v.visitFoo(*this);
}
};
class Bar: public Arbitrary
{
public:
virtual void DoSomething()
{
cout<<"do Bar specific stuff"<<endl;
}
virtual void accept(ArbitraryVisitor& v)
{
v.visitBar(*this);
}
};
class SetArbitaryVisitor : public ArbitraryVisitor
{
void visitParent(Arbitrary& vm)
{
vm.DoSomething();
}
void visitFoo(Foo& vm)
{
vm.DoSomething();
}
void visitBar(Bar& vm)
{
vm.DoSomething();
}
};
int main()
{
Arbitrary *arb = new Foo();
SetArbitaryVisitor scv;
arb->accept(scv);
}