У меня есть класс кнопки Button, в котором я создал указатель на функцию, которая должна исполняться по нажатию на кнопку. Эдакий коллбэк, задаваемый извне.
В определенном месте кода, мне нужно использовать в этом коллбэке текст, введенный пользователем в текстовое поле, что происходит в определенном классе.
Но я получаю ошибку login.cpp|80|undefined reference to Login::tf
Как мне добиться того, чтобы объявленная вне класса функция, могла обратиться к его данным, и использовать/изменять их?
Вот код класса Button ниже;
То, что я посчитал маловажным убрано, но если что, полный код лежит на github:
(если это возможно, я бы хотел оставить интерфейс этого класса без изменений, так как он много где используется)
///Класс кнопки. Обрабатывает клик, выполняет скормленную ему функцию реакции на него.
class Button : public AbstractUIElement
{
/*стандартный цвет кнопки, цвет при вхождении курсора в область кнопки*/
public:
void (onClick)(StateBasedGame, SDL_Event*); // функция-обработчик клика
/// можно создать кнопку, не устанавливая функцию, которую она будет выполнять
Button(char* myText) {/*...*/}
/// инициализация кнопки функцией, которую она выполняет
Button( void (*callback)(StateBasedGame* e, SDL_Event* g), char* myText )
{
onClick = callback;
/*...*/
}
void update(StateBasedGame* g, SDL_Event* e)
{
if( e->type == SDL_MOUSEMOTION || e->type == SDL_MOUSEBUTTONDOWN || e->type == SDL_MOUSEBUTTONUP )
{
int x, y;
SDL_GetMouseState( &x, &y );
bool inside = true;
if( x < bounds.x )
{
inside = false;
}
else if( x > bounds.x + bounds.w )
{
inside = false;
}
else if( y < bounds.y )
{
inside = false;
}
else if( y > bounds.y + bounds.h )
{
inside = false;
}
if( !inside )
{
color = backup_color;
}
else
{
switch( e->type )
{
case SDL_MOUSEMOTION:
color = ACTIVE_COLOR;
break;
case SDL_MOUSEBUTTONDOWN:
color = CLICK_COLOR;
onClick(g, e);
break;
case SDL_MOUSEBUTTONUP:
color = CLICK_COLOR;
onClick(g, e);
break;
}
}
}
}
void setCallback (void (*callback)(StateBasedGame* e, SDL_Event* g))
{
this->onClick = callback;
}
};
А вот класс, данные которого должна использовать кнопка. В TextField tf вводится имя, которое по нажатию на кнопку должно записаться в глобальную структуру, отвечающую за пользователей в текущей сессии. Код выложен практически полностью, но вот на всякий случай ссылка на него в том же проекте.
#ifndef LOGIN
#define LOGIN
using namespace std;
static void loginOnClick(StateBasedGame* g , SDL_Event* e);
class Login : public GameState
{
SDL_Event event;
SDL_Surface* screen;
Button* back_button;
Label* text;
public:
static TextField tf;
void init( SDL_Surface* display, StateBasedGame* g )
{
screen = display;
back_button = new Button(loginOnClick, "Продолжить");
back_button->bounds.x = (display->w - back_button->bounds.w)/2;
back_button->bounds.y = display->h - back_button->bounds.h - 50;
text = new Label("Введите имя:");
text->bounds.w = 300;
text->bounds.x = (screen->w - text->bounds.w)/2;
text->bounds.y = screen->h/2-50;
tf.bounds.w = 300;
tf.bounds.x = (screen->w - tf.bounds.w)/2;
tf.bounds.y = screen->h/2;
}
void update( StateBasedGame* g, int delta )
{
if(SDL_PollEvent(&event)) {
if(event.type == SDL_QUIT) g->exit();
tf.update(event);
}
back_button->update(g, &event);
}
void render( SDL_Surface* display )
{
back_button->render(display);
text->render(display);
tf.render(display);
}
SDL_Event* pollEvent( void )
{
return &event;
}
SDL_Surface* getScreen()
{
return screen;
}
~Login()
{
delete back_button;
delete text;
}
};
#ifndef LOGIN_ON_CLICK
#define LOGIN_ON_CLICK
static void loginOnClick(StateBasedGame* g , SDL_Event* e)
{
Player* player = new Player((Login::tf).text);
current_session.players.push_back(player);
current_session.current_player = player;
g->switchState(states::main_menu);
}
#endif // LOGIN_ON_CLICK
#endif // LOGIN
Я пробовал следующее:
- создавать функцию статической до объявления класса, но тогда она не знает о его существовании, и как следствие не может обратиться к его членам
- создавать её и статической и не статической внутри класса. Позже нашёл объяснение в интернете, что это так работать не будет. Там есть пример рабочего синтаксиса, но он, на сколько я понял, будет привязан к одному конкретному классу, а мне нужен подход, который позволит использовать подобные конструкции в будущем и для других классов - универсальная кнопка, какой она до сих пор и была, пока не потребовался доступ к членам класса-пользователя кнопки.
- пробовал пользоваться лямбда-выражением вместо создания функции, и передачи её указателя позже, но запутался в синтаксисе, и словил столько ошибок, что оставил идею, и вернулся к ранее работавшему варианту с отдельной функцией. Сама идея реализовать функцию прямо на месте присвоения, как анонимный объект в java, мне нравится.
Буду рад, если поможете починить мои кнопки, и объясните, что я делаю не так. Заранее спасибо.