Nor base nor derived virtual function being properly called - arduino

I have this base class:
// put the display in a macro on a .h file for less headache.
class Gadget {
protected:
int x, y;
U8GLIB * u8g;
virtual int f_focus() {return 0;};
virtual int f_blur() {return 0;};
virtual void f_draw() {};
virtual void f_select() {};
public:
Gadget(U8GLIB * u8g, int x, int y) :
u8g(u8g),
x(x),
y(y)
{
Serial.println(F("Gadget(U8GLIB * u8g, int x, int y)"));
};
Gadget() {
Serial.println(F("Gadget()"));
};
int focus(){return f_focus();};
int blur(){return f_blur();};
void draw(){f_draw();};
void operator()(){f_select();};
};
And this derived class:
class WakeUp :
public Gadget
{
public:
WakeUp(U8GLIB * u8g) :
Gadget(u8g, 0, 0)
{
Serial.println(F("WakeUp(U8GLIB * u8g)"));
};
};
Then I instantiate the WakeUp class inside an array like this:
Gadget gadgets[1] = {
WakeUp(&u8g)
};
Then I try to access this member like this:
void focus() {
Serial.println(gadgets[0].focus());
}
It is supposed to display 0. However it is displaying -64. Even if I override the f_focus() method on WakeUp class. If I remove the virtual specifier from f_focus() it works fine, displaying 0, but I will not be able to access the derived class implementation of this method.
I wish to understand what is causing this strange behavior and what can I do to avoid it.
EDIT:
The function runs fine if I call it from the Gadget Constructor.

You're slicing your WakeUp object.
You essentially have the following:
Gadget g = WakeUp(...);
What this code does is the following:
Construct a WakeUp object.
Call Gadget(const Gadget& other) with the base from the WakeUp object.
Destroy the temporary WakeUp object, leaving only the copy of the Gadget base.
In order to avoid this, you need to create an array of pointers (this is better if they are smart pointers).
Gadget* gadgets[1] = { new WakeUp(&u8g) }; // If you choose this method, you need to call
// delete gadget[0] or you will leak memory.
Using a pointer will correctly preserve the Gadget and WakeUp instances instead of slicing them away.
With smart pointers:
std::shared_ptr<Gadget> gadgets[1] = { std::make_shared<WakeUp>(&u8g) };

Related

After I declare an object from a class, and try to set a variable to that object inly, why does it say that it does not declare a type?

I am writing code for a school project that will be used for a Chromebook charging station with security. The problem I am having now is when I am detecting if a Chromebook is actually in the slot after the user has been assigned one, I am using a rocker switch to simulate this but when I am declaring the pin to the rocker, the arduino verfier comes up with that
"'slot1' does not name a type".
Code is below:
//class
class Chromebook_slot {
public:
String Name = "";
String RFID_tag = "";
int rocker = 0;
boolean chromebook_in = false;
//class function to check if chromebook is in.
//if not, redirect already to reassigning so chromebook slot is entered as open and free.
void set_if_in()
{
int momen_1_state = digitalRead(momen_1);
int momen_2_state = digitalRead(momen_2);
// the button has been pushed down and the previous process has been completed
// eg. servos would have been reset if there was a previous user
if (momen_1_state == HIGH || momen_2_state == HIGH)
{
chromebook_in = digitalRead(this->rocker);
if (chromebook_in == 0)
{
re_assigning();
}
else
{
return;
}
}
}
};
//this is now outside the class..
//class declarations
Chromebook_slot slot1;
Chromebook_slot slot2;
//variables for rocker switches which will act for detecting chromebooks.
// in my final version, this will replaced by a photoresistor and laser.
slot1.rocker = 3;
slot2.rocker = 2;
Where the function re_assigning() is a separate function declared further in the code and just resets the slot as open for future use.
slot1.rocker = 3;
slot2.rocker = 2;
These are statements that cannot be at the top level of a C++ (or .ino) file. They need to be inside of a function. What's happening is the compiler is looking looking at the slot1 identifier through the lens of potential valid constructions. It sees an identifier, and about the only thing that could legally exist at this point in the code that starts with an identifier like that is some declaration, e.g. int a = 7;, or more abstractly some_type some_more_stuff. So it expects slot1 to be a type, which it isn't, hence the message.
If you want an assignment like those to happen early on in an Arduino program, the simplest thing you could do is put them in setup():
void setup() {
slot1.rocker = 3;
slot2.rocker = 2;
// ...
}
Or, you'd make these part of the Chromebook_slot's constructor, such that they could be given in slot1 and slot2's declaration:
class Chromebook_slot {
public:
Chromebook_slot(int rocker_init_value) {
rocker = rocker_init_value;
}
// ...
Or in a maybe less familiar but more proper form, using the constructor's initialization list:
class Chromebook_slot {
public:
Chromebook_slot(int rocker_init_value)
: rocker(rocker_init_value) {}
// ...
Once you have a constructor for Chromebook_slot, your variables can become:
Chromebook_slot slot1(3);
Chromebook_slot slot2(2);

MQL4/5 CList Search method always returning null pointer

I'm trying to use the CList Search method in an application. I have attached a very simple example below.
In this example, I always get a null pointer in the variable result. I tried it in MQL4 and MQL5. Has anyone ever made the Search method work? If so, where is my mistake? With my question, I refer to this implementation of a linked list in MQL (it's the standard implementation). Of course, in my application, I do not want to find the first list item, but items that match specific criteria. But even this trivial example does not work for me.
#property strict
#include <Arrays\List.mqh>
#include <Object.mqh>
class MyType : public CObject {
private:
int val;
public:
MyType(int val);
int GetVal(void);
};
MyType::MyType(int val): val(val) {}
int MyType::GetVal(void) {
return val;
}
void OnStart() {
CList *list = new CList();
list.Add(new MyType(3));
// This returns a valid pointer with
// the correct value
MyType* first = list.GetFirstNode();
// This always returns NULL, even though the list
// contains its first element
MyType* result = list.Search(first);
delete list;
}
CList is a kind of linked list. A classical arraylist is CArrayObj in MQL4/5 with Search() and some other methods. You have to sort the list (so implement virtual int Compare(const CObject *node,const int mode=0) const method) before calling search.
virtual int MyType::Compare(const CObject *node,const int mode=0) const {
MyType *another=(MyType*)node;
return this.val-another.GetVal();
}
void OnStart(){
CArrayObj list=new CArrayObj();
list.Add(new MyType(3));
list.Add(new MyType(4));
list.Sort();
MyType *obj3=new MyType(3), *obj2=new MyType(2);
int index3=list.Search(obj3);//found, 0
int index2=list.Search(obj2);//not found, -1
delete(obj3);
delete(obj2);
}

C++/CLI: wrapping the same unmanaged object in multiple managed objects

I am developing a library which has two layers, unmanaged (C++) and managed (C++/CLI). The unmanaged layer contains the logics and the computation algorithms, while the managed layer provides interface and visualisation to a .NET-based host application. A class in the managed layer wraps its class counterpart in the unmanaged layer, e.g. ManagedA wraps UnmanagedA and ManagedB wraps UnmanagedB.
Classes in the unmanaged layer have query methods, suppose UnmanagedA::B() returns an instance of UnmanagedB. For visualisation, I need to wrap this instance in a ManagedB instance. The problem is, if I repeat this process twice, I am creating two ManagedB instances which points to the same UnmanagedB instance. Because the ManagedB instances are disposed, the same UnmanagedB instance is deleted twice, which should not happen.
So I would like to know the best practice or strategy to wrap an unmanaged object in a managed object.
Here is a code which emulates this behaviour. I understand that you don't need to explicitly delete the managed objects, but I use it here just to emulate the deletion sequence.
Many thanks.
#include "stdafx.h"
using namespace System;
class UnmanagedB
{
public:
UnmanagedB() {}
~UnmanagedB() {}
int i = 0;
};
class UnmanagedA
{
public:
UnmanagedA(UnmanagedB* pUnmanagedB)
: m_pUnmanagedB(pUnmanagedB)
{
}
~UnmanagedA() {}
UnmanagedB* B() { return m_pUnmanagedB; }
protected:
UnmanagedB* m_pUnmanagedB;
};
public ref class ManagedA : IDisposable
{
public:
ManagedA(UnmanagedA* pUnmanagedA)
: m_pUnmanagedA(pUnmanagedA)
{
}
~ManagedA()
{
delete m_pUnmanagedA;
}
private:
UnmanagedA* m_pUnmanagedA;
};
public ref class ManagedB : IDisposable
{
public:
ManagedB(UnmanagedB* pUnmanagedB)
: m_pUnmanagedB(pUnmanagedB)
{
}
~ManagedB()
{
delete m_pUnmanagedB;
}
private:
UnmanagedB * m_pUnmanagedB;
};
int main(array<System::String ^> ^args)
{
UnmanagedB* pUnmanagedB = new UnmanagedB();
UnmanagedA* pUnmanagedA = new UnmanagedA(pUnmanagedB);
ManagedB^ pManagedB1 = gcnew ManagedB(pUnmanagedA->B());
ManagedB^ pManagedB2 = gcnew ManagedB(pUnmanagedA->B());
delete pManagedB1;
delete pManagedB2; // will crash here because the destructor deletes pUnmanagedB, which is already deleted in the previous line
delete pUnmanagedA;
return 0;
}
This is a typical case using a smart pointer.
So don't store UnmanagedA* and UnmanagedB* use shared_ptr and shared_ptr
Becaus ethe managed class can only carry a plain pointer to an unmannged class you have to redirect it again and use:
shared_ptr<UnmanagedA>* pManagedA;
A simple accessor function will help you to use the pointer:
shared_ptr<UnmanagedA> GetPtrA() { return *pManagedA; }
All plain pointer to the unmanaged classes should be shared_ptr instances. In your main use make_shared instead of new. Or direct the pointer created by new into a shared_ptr...
Here is one class rewritten:
public ref class ManagedA : IDisposable
{
public:
ManagedA(shared_ptr<UnmanagedA> pUnmanagedA)
{
m_pUnmanagedA = new shared_ptr<UnmanagedA>();
*m_pUnmanagedA = pUnmanagedA;
}
~ManagedA()
{
delete m_pUnmanagedA;
}
void Doit()
{
GetPtrA()->DoSomething();
}
private:
shared_ptr<UnmanagedA>* m_pUnmanagedA;
shared_ptr<UnmanagedA> GetPtrA() { return *m_pUnmanagedA; }
};

Qt novice: base class for QLineEdit and QTextEdit

Is there another class besides QWidget which holds all generic functions for both? Something like QEdit...
As an example I'd like to reference cut(), copy() and paste(), but it looks like I have to dynamic cast the QWidget. Is there any other way?
There is no other way besides QWidget. The reason is that QLineEdit is inherited directly from QWidget. You can see the full hierarchy of Qt classes here
You don't have to dynamic-cast anything: this is typically a sign of bad design. Qt generally has very few interface classes - they usually have the word Abstract somewhere in the name, and are not really pure interfaces as they have non-abstract base classes, like e.g. QObject. Thus there was no pattern to follow, and no need for abstracting out the edit operations into an interface.
There are several approaches to overcome this:
Leverage the fact that the methods in question are known by the metaobject system. Note that invokeMethod takes a method name, not signature.
bool cut(QWidget * w) {
return QMetaObject::invokeMethod(w, "cut");
}
bool copy(QWidget * w) {
return QMetaObject::invokeMethod(w, "copy");
}
//...
You can use the free-standing functions such as above on any widget that supports the editing operations.
As above, but cache the method lookup not to pay its costs repeatedly. Note that indexOfMethod takes a method signature, not merely its name.
static QMetaMethod lookup(QMetaObject * o, const char * signature) {
return o->method(o->indexOfMethod(signature));
}
struct Methods {
QMetaMethod cut, copy;
Methods() {}
explicit Methods(QMetaObject * o) :
cut(lookup(o, "cut()")),
copy(lookup(o, "copy()")) {}
Methods(const Methods &) = default;
};
// Meta class names have unique addresses - they are effectively memoized.
// Dynamic metaobjects are an exception we can safely ignore here.
static QMap<const char *, Methods> map;
static const Methods & lookup(QWidget * w) {
auto o = w->metaObject();
auto it = map.find(o->className());
if (it == map.end())
it = map.insert(o->className(), Methods(o));
return *it;
}
bool cut(QWidget * w) {
lookup(w).cut.invoke(w);
}
bool copy(QWidget * w) {
lookup(w).copy.invoke(w);
}
//...
Define an interface and provide implementations specialized for widget types. This approach's only benefit is that it's a bit faster than QMetaMethod::invoke. It makes little sense to use this code for clipboard methods, but it could be useful to minimize overhead for small methods that are called very often. I'd advise not to over-engineer it unless a benchmark shows that it really helps. The previous approach (#2 above) should be quite sufficient.
// Interface
class IClipboard {
public:
virtual cut(QWidget *) = 0;
virtual copy(QWidget *) = 0;
virtual paste(QWidget *) = 0;
};
class Registry {
// all meta class names have unique addresses - they are effectively memoized
static QMap<const char *, IClipboard*> registry;
public:
static void register(const QMetaObject * o, IClipboard * clipboard) {
auto name = o->className();
auto it = registry.find(name);
if (it == registry.end())
registry.insert(name, clipboard);
else
Q_ASSERT(it->value() == clipboard);
}
static IClipboard * for(QWidget * w) {
auto it = registry.find(w->metaObject()->className());
Q_ASSERT(registry.end() != it);
return it->value();
}
static void unregister(const QMetaObject * o) {
registry.remove(o->className());
}
};
template <class W> class ClipboardWidget : public IClipboard {
Q_DISABLE_COPY(ClipboardWidget)
public:
cut(QWidget * w) override { static_cast<W*>(w)->cut(); }
copy(QWidget * w) override { static_cast<W*>(w)->copy(); }
paste(QWidget * w) override { static_cast<W*>(w)->paste(); }
ClipboardWidget() {
Registry::register(&W::staticMetaObject(), this);
}
~ClipboardWidget() {
Registry::unregister(&W::staticMetaObject());
}
};
// Implementation
QMap<const char *, IClipboard*> Registry::registry;
static ClipboardWidget<QTextEdit> w1;
static ClipboardWidget<QLineEdit> w2;
void yourCode() {
//...
Registry::for(widget)->cut(widget);
}

vector base derived class

I am not able to call negedge of all the subscribers who register for clock, all subscribers also derive from ClkIf
class ClkAdapter : public ClkIf
{
virtual void negedge()
{
for(std::list<ClkIf*>::iterator it = clk_list.begin(); it != clk_list.end(); it++)
(it->negedge)();
}
virtual void posedge()
{ clk_cnt++; }
void registerForClock(ClkIf* module)
{ clk_list.push_back(module); }
std::list<ClkIf*> clk_list;
unsigned long long clk_cnt;
};
error: request for member 'negedge' in '* it.std::_List_iterator<_Tp>::operator-> with _Tp = ClkIf*', which is of non-class type 'ClkIf*'
Error in negedge function, What is wrong in this code??
You have a list of pointers, so the list iterator would work similarly to a double pointer (that is, ClkIf**). Thus, you would have to call (*it)->negedge() within the loop. The (*it) fetchs the current ClkIf* element first, and then the -> operator calls the function on that value.

Resources