Hi @Gianfry7 - I don’t know what your bug is but I do this all the time.
The general idea is base class includes a type identifier as you’ve done.
A struct containing a union of all the derived type sets the required
queue entry size and provides a method to cast the union back to the base class.
Below is an example from production code.
Hope this helps!
/// Display queue entries are derived from abstract base class Display_queue_entry_BaseT.
/// A virtual function implements the UpdateDisplay operation (in display.cpp).
/// Because we're copying objects into and out of fixed-length queue entries,
/// union class DispReq_Union_T below manages queue entry processing and size...
class Display_queue_entry_BaseT {
public:
// Because we've not enabled RTTI, specializations use an explicit type
enum class FakeTypeID_T {
Unknown,
FixedMessage,
MeasurementSet,
SetBrightness,
Mastering,
AdviseStopped,
};
const FakeTypeID_T fakeTypeID;
uint8_t holdSeconds; //> freeze display for this many seconds after displaying payload
bool Enqueue() const; //> copy this queue_entry to the back of display input queue
virtual void UpdateDisplay(void) const = 0;
protected:
Display_queue_entry_BaseT(FakeTypeID_T _fakeTypeID, uint8_t _hold) :
fakeTypeID(_fakeTypeID), holdSeconds(_hold) {};
private:
Display_queue_entry_BaseT(); // no default ctor implemented
};
/// Fixed-message from predefined enumeration
class DispReq_FixedMessage_T : public Display_queue_entry_BaseT {
private:
bool blinkControlMsg; // this is a blink-control message (internal to display process)
bool blinkOff; // blank display (then delay and turn it back on)
public:
virtual void UpdateDisplay(void) const;
typedef enum {
Question_Upload, // "Upload measurement history?",
Question_Erase, // "Erase measurement history?",
Wait_Uploading, // "Uploading, please wait...",
Wait_Erasing, // "Erasing, please wait..."
Wait_Saving, // "Saving, please wait..."
FixedTextCount, // count of valid indexed-text messages above
Herald,
} MsgIdx_T;
MsgIdx_T msgIdx;
bool blink; //> annoy user by flashing this message on the display?
// Three labels to be displayed at bottom of OLED (just above the buttons below the OLED)
typedef enum { ButtonLabels_NO_blank_YES, ButtonLabels_Count, ButtonLabels_None, } ButtonLabels_T;
ButtonLabels_T buttonLabels;
DispReq_FixedMessage_T(MsgIdx_T _msgIdx, uint8_t _hold, bool _blink=false, ButtonLabels_T _buttonLabels=ButtonLabels_None) :
Display_queue_entry_BaseT(FakeTypeID_T::FixedMessage,_hold),
blinkControlMsg(false), blinkOff(false),
msgIdx(_msgIdx), blink(_blink), buttonLabels(_buttonLabels) {};
};
/// Measurement Set display message: up to 3 measurements depending on personality
class DispReq_MeasurementSet_T : public Display_queue_entry_BaseT {
void dispMeasurementMode() const;
void dispSiteLocation() const;
void dispAssetTag() const;
public:
virtual void UpdateDisplay(void) const;
ProductX::C_MeasurementSet ms;
typedef enum {
LIVE,
HOLD,
MIN,
Cnt
} MeasurementMode_T;
MeasurementMode_T measurementMode;
struct ProductYIndividual_S {
bool displayIndividuals;
int displayNumbers[3];
ProductYIndividuals_S() : displayIndividuals(false), displayNumbers{0,0,0} {};
bool operator == (const ProductYIndividuala_S &x) const { return 0==memcmp((const void*)this, (const void*)&x, sizeof(*this)); };
bool operator != (const ProductYIndividuala_S &x) const { return !(x == *this); };
} ProductYIndividuala;
DispReq_MeasurementSet_T(const ProductX::C_MeasurementSet &_ms, MeasurementMode_T _mode, ProductYIndividuala_S _ProductYIndividuala = ProductYIndividuala_S()) :
Display_queue_entry_BaseT(FakeTypeID_T::MeasurementSet,0),
ms(_ms), measurementMode(_mode), ProductYIndividuala(_ProductYIndividuala)
{};
};
/// SetBrightness: Set brightness (without task contention issues)
class DispReq_SetBrightness_T : public Display_queue_entry_BaseT {
public:
virtual void UpdateDisplay(void) const;
uint8_t brightness;
DispReq_SetBrightness_T(uint8_t _brightness) :
Display_queue_entry_BaseT(FakeTypeID_T::SetBrightness, 0), brightness(_brightness) {};
};
/// Mastering prompt displays master as set on PC (plus channel label for ProductY)
class DispReq_MasteringPrompt_T : public Display_queue_entry_BaseT {
int idx; // prompt for which?
public:
virtual void UpdateDisplay(void) const;
DispReq_MasteringPrompt_T(int _idx) :
Display_queue_entry_BaseT(FakeTypeID_T::Mastering, 0), idx(_idx) {};
};
/// If most recent display is a measurement, note that processing is stopped
class DispReq_AdviseStopped_T : public Display_queue_entry_BaseT {
public:
virtual void UpdateDisplay(void) const;
DispReq_AdviseStopped_T() :
Display_queue_entry_BaseT(FakeTypeID_T::AdviseStopped, 0) {};
};
/// Union is the max size of all possible display request objects,
/// and provides a convenient class to receive objects from queue.
/// Must contain *all* possible classes above!
struct DispReq_Union_T {
union uT {
DispReq_FixedMessage_T a;
DispReq_MeasurementSet_T b;
DispReq_SetBrightness_T c;
DispReq_MasteringPrompt_T d;
DispReq_AdviseStopped_T e;
uT() {}; // default ctor required (for DispReq_Union_T's default ctor)
} u;
Display_queue_entry_BaseT const & GetBaseDisplayRequest()
{ return (Display_queue_entry_BaseT&)u; };
};