Я создаю ЖК-меню, и у меня проблемы с взаимодействием lcdmenu
(главное меню) и submenu
.
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)
{
}
Я передаю список экземпляров submenu
в переменную lcdmenu.submenulist
и хочу lcdmenu::render()
вызвать lcd_string(submenulist[index]->get_text());
, но не могу использовать submenu.get_text
, если этот метод еще не определен.
Есть ли способ отформатировать мой файл, чтобы я мог использовать как полностью определенный класс lcdmenu
, так и submenu
классы друг в друге?
Если у вас публичное наследование без виртуальных функций, возможно, вы делаете что-то не так.
Вы не можете использовать метод класса до его объявления.
Использование прямого объявления — правильный способ устранения циклических ссылок между классами. Итак, то, что вы делаете для члена lcdmenu::submenulist
(и, предположительно, то же самое для члена lcdmenu::commandlist
), вполне подходит для объявления класса lcdmenu
.
Но предварительное объявление не помогает реализации метода lcdmenu::render()
. Для доступа к его членам требуется полное объявление класса submenu
, например метод submenu::get_text()
(и то же самое с классом command
).
Итак, вам нужно разделить ваши объявления и реализации на отдельные файлы .h
и .cpp
, чтобы облегчить эту задачу, например:
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());
}
подменю.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
подменю.cpp
#include "submenu.h"
submenu::submenu(lcdmenu *par, const char* text_):text(text_), parent(par)
{
}
const char* submenu::get_text(){
return text;
}
команда.h
#ifndef command_H
#define command_H
...
class command ... {
public:
...
const char* get_text();
};
#endif
команда.cpp
#include "command.h"
...
const char* command::get_text(){
return ...;
}
Теперь при компиляции lcdmenu.cpp
компилятор после замен препроцессора увидит следующий код:
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());
}
И когда вы скомпилируете submenu.cpp
, компилятор после замен препроцессора увидит следующий код:
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;
}
И когда вы скомпилируете command.cpp
, компилятор после замен препроцессора увидит следующий код:
...
class command ... {
public:
...
const char* get_text();
};
...
const char* command::get_text(){
return ...;
}
Это идеально, спасибо!
Рад, что это помогает. Теперь, пожалуйста, прочтите Что мне делать, если кто-то отвечает на мой вопрос?
Сделаю! Я получаю ошибку компиляции: когда я включаю lcdmenu.cpp в add_executable()
моего файла cmake, я получаю ошибку multiple definition
, но когда я удаляю его из функции, я получаю ошибку undefined reference
. (также у меня недостаточно репутации, чтобы проголосовать, извините)
Тогда вы скорее всего что-то не правильно настроили при разделении. Но это следует опубликовать как новый вопрос с минимально воспроизводимым примером.
Что вы подразумеваете под «методом студента»? Вы имели в виду «метод подкласса»?