I'm making an LCD menu and having trouble with the lcdmenu
(main menu) and submenu
interaction.
class submenu;
class lcdmenu
{
protected:
command **commandlist;
submenu **submenulist;
...
public:
void setchildren(command **comlist, submenu **sublist, int comn, int subn);
void render();
...
};
void lcdmenu::render(){
lcd_clear();
for (int line = 0; line < MAX_LINES; line ++){
int index = menutop + line;
...
if (index < numcommands){
lcd_string(commandlist[index]->get_text());
lcd_string(submenulist[index]->get_text());
}
class submenu : public lcdmenu {
public:
lcdmenu *parent;
submenu(lcdmenu *par, const char* text);
const char* get_text(){
return text;
}
};
submenu::submenu(lcdmenu *par, const char* text_):text(text_), parent(par)
{
}
I am passing a list of submenu
instances into the lcdmenu.submenulist
variable, and I want lcdmenu::render()
to call lcd_string(submenulist[index]->get_text());
but I can not use submenu.get_text
when that method has not been defined yet.
Is there a way to format my file so I can use both the fully defined lcdmenu
class and submenu
classes within each other?
You can't use a class method before it has been declared.
Using a forward declaration is the correct way to address circular references between classes. So what you are doing for the lcdmenu::submenulist
member (and presumably the same for the lcdmenu::commandlist
member) is perfectly fine for the purpose of declaring the lcdmenu
class.
But, the forward declaration does not help the implementation of the lcdmenu::render()
method. It needs the full declaration of the submenu
class in order to access its members, such as the submenu::get_text()
method (and the same with the command
class).
So, you need to split up your declarations and implementations into separate .h
and .cpp
files to help facilitate this task, eg:
lcdmenu.h
#ifndef lcdmenu_H
#define lcdmenu_H
class command;
class submenu;
class lcdmenu
{
protected:
command **commandlist;
submenu **submenulist;
...
public:
void setchildren(command **comlist, submenu **sublist, int comn, int subn);
void render();
...
};
#endif
lcdmenu.cpp
#include "lcdmenu.h"
#include "submenu.h"
#include "command.h"
...
void lcdmenu::render(){
lcd_clear();
for (int line = 0; line < MAX_LINES; line ++){
int index = menutop + line;
...
if (index < numcommands){
lcd_string(commandlist[index]->get_text());
lcd_string(submenulist[index]->get_text());
}
submenu.h
#ifndef submenu_H
#define submenu_H
#include "lcdmenu.h"
class submenu : public lcdmenu {
public:
lcdmenu *parent;
submenu(lcdmenu *par, const char* text);
const char* get_text();
};
#endif
submenu.cpp
#include "submenu.h"
submenu::submenu(lcdmenu *par, const char* text_):text(text_), parent(par)
{
}
const char* submenu::get_text(){
return text;
}
command.h
#ifndef command_H
#define command_H
...
class command ... {
public:
...
const char* get_text();
};
#endif
command.cpp
#include "command.h"
...
const char* command::get_text(){
return ...;
}
Now, when you compile lcdmenu.cpp
, the compiler will see the following code after preprocessor substitutions:
class command;
class submenu;
class lcdmenu
{
protected:
command **commandlist;
submenu **submenulist;
...
public:
void setchildren(command **comlist, submenu **sublist, int comn, int subn);
void render();
...
};
class submenu : public lcdmenu {
public:
lcdmenu *parent;
submenu(lcdmenu *par, const char* text);
const char* get_text();
};
...
class command ... {
public:
...
const char* get_text();
};
...
void lcdmenu::render(){
lcd_clear();
for (int line = 0; line < MAX_LINES; line ++){
int index = menutop + line;
...
if (index < numcommands){
lcd_string(commandlist[index]->get_text());
lcd_string(submenulist[index]->get_text());
}
And when you compile submenu.cpp
, the compiler will see the following code after preprocessor substitutions:
class command;
class submenu;
class lcdmenu
{
protected:
command **commandlist;
submenu **submenulist;
...
public:
void setchildren(command **comlist, submenu **sublist, int comn, int subn);
void render();
...
};
class submenu : public lcdmenu {
public:
lcdmenu *parent;
submenu(lcdmenu *par, const char* text);
const char* get_text();
};
submenu::submenu(lcdmenu *par, const char* text_):text(text_), parent(par)
{
}
const char* submenu::get_text(){
return text;
}
And when you compile command.cpp
, the compiler will see the following code after preprocessor substitutions:
...
class command ... {
public:
...
const char* get_text();
};
...
const char* command::get_text(){
return ...;
}