I was getting an error in something called TouchGFX and it was pointed out to me that a virtual function inside a class needed to be defined with curly braces vs just a semicolon at the end of its name. I can do basic C++ but inheritance, virtual functions, etc are not something I use often.
What's the difference between #1 and #2 way to define the virtual function setTimeDate()
?
TouchGFX allows you to create "screens" for the display. Like your cellphone display. Turn it on and there is a screen. If you swipe or open an app you get a different screen.
There are two classes that are for all screens (model
and modelListener
). Each screen in the project gets two more classes (Presenter
and a View
). I showed below the classes for the principalScreen
but there is another ... SecondScreen
. There are no virtual functions defined in the SecondScreen
... I haven't gotten to that part of the code yet. The error I was getting was:
./Application/User/gui/SecondScreenPresenter.o:(.rodata._ZTV21SecondScreenPresenter+0x28):undefined reference to `ModelListener::setTime(displayTime_t)'
osMessageQueueGetCount, osMessageQueueGet are part of [CMSIS-RTOS2](https://www.keil.com/pack/doc/CMSIS/RTOS2/html/group__CMSIS__RTOS__Message.html).
I only changed the definition inside the model
class and the error went away.
virtual void setTime(displayTime_t time); // #1 error
virtual void setTime(displayTime_t time){} // #2 correct
class ModelListener
{
public:
ModelListener() : model(0) {}
virtual ~ModelListener() {}
void bind(Model* m)
{
model = m;
}
virtual void setTimeDate(displayTimeDate_t nTimeDate){}
protected:
Model* model;
};
Model::Model() : modelListener(0), newTimeDate({0})
{
}
void Model::tick()
{
if(osMessageQueueGetCount(qRTCtoUIHandle)>0)
{
if(osMessageQueueGet(qRTCtoUIHandle, &newTimeDate, 0, 0)==osOK)
{
modelListener->setTimeDate(newTimeDate);
}
}
}
class principalScreenPresenter : public touchgfx::Presenter, public ModelListener
{
public:
principalScreenPresenter(principalScreenView& v);
/**
* The activate function is called automatically when this screen is "switched in"
* (ie. made active). Initialization logic can be placed here.
*/
virtual void activate();
/**
* The deactivate function is called automatically when this screen is "switched out"
* (ie. made inactive). Teardown functionality can be placed here.
*/
virtual void deactivate();
virtual ~principalScreenPresenter() {};
virtual void setTimeDate(displayTimeDate_t nTimeDate);
private:
principalScreenPresenter();
principalScreenView& view;
};
class principalScreenView : public principalScreenViewBase
{
public:
principalScreenView();
virtual ~principalScreenView() {}
virtual void setupScreen();
virtual void tearDownScreen();
virtual void setTimeDate(displayTimeDate_t nTimeDate);
protected:
};
I was following a YouTube video to do this, but using a struct instead of an int like in the video, I thought I accidentally copy/pasted the function in a different file. But after a few hours of trying stuff, I discovered that it was related to a screen interaction. I couldn't figure the error out on my own.
I asked in the STM forum and someone gave me the answer. I'm trying to understand more about the solution. My C++ book (very old) talks about virtual functions, but not this small difference. There is lots of stuff online, but I could find an explanation for this.