Сбой: при доступе к вектору из класса - PullRequest
2 голосов
/ 14 марта 2019

Я программирую пользовательский интерфейс ESP32 и столкнулся с этой проблемой:

У меня есть класс Menu, и я определяю вектор _menuItemStack в его заголовке.

Я создаю Object MenuItem извне и передаю его в функцию addMenuItem (MenuItem menuItem). Он добавляет его в стек. Что работает, когда я объявляю вектор в Menu.cpp, он запускается. Но он не будет уникальным для каждого объекта, я думаю, что он становится статичным?

Итак, я объявил вектор как частный в заголовке, пока он будет компилироваться. он сразу падает.

В чем моя ошибка? С ++ у меня болит голова.

Menu.h

    /*
  Menu.h - Menu Class
*/
#ifndef Menu_h
#define Menu_h

#include "Arduino.h"
#include "StackArray.h"
#include "MenuItem.h"
#include "SPI.h"
#include "U8g2lib.h"

class Menu
{
  public:
    Menu();
    void update();
    void draw();
    void addMenuItem(MenuItem menuItem);
  private:
    int arrayPos;
    std::vector<MenuItem> _menuItemStack;
};

#endif

Menu.cpp

#include "Menu.h"
extern U8G2_SSD1327_MIDAS_128X128_2_4W_HW_SPI u8g2;

Menu::Menu() {
  arrayPos = 0;
}

void Menu::draw() {

  u8g2.setFont(u8g2_font_6x10_tf);

  int posY = 0;

  for (MenuItem &m : _menuItemStack){
    u8g2.drawStr(0,posY+15,m.getText().c_str());
    posY+=15;
  }
}
void Menu::update() {

}

void Menu::addMenuItem(MenuItem menuItem){
  arrayPos++;
  _menuItemStack.push_back(menuItem);

  //debug
  Serial.println(arrayPos);
  Serial.println(menuItem.getText());
}

Примечания: std :: stdlib включен выше.

EDIT:

MenuItem.cpp

#include "MenuItem.h"
extern U8G2_SSD1327_MIDAS_128X128_2_4W_HW_SPI u8g2;

MenuItem::MenuItem() {
  _text = new String;
}

MenuItem::MenuItem(const MenuItem &obj){
  _text = new String;
  *_text = *obj._text;
}

void MenuItem::draw(){

}
void MenuItem::update(){

}

void MenuItem::setText(String txt){
  *_text = txt;
}

String MenuItem::getText(){
  return *_text;
}

void MenuItem::attachHandler(CallbackFunction f){
  callback = f;
}

void MenuItem::run(){
  if (callback != NULL) callback();
}

MenuItem.h

#ifndef MenuItem_h
#define MenuItem_h

#include "Arduino.h"
#include "StackArray.h"
#include "SPI.h"
#include "U8g2lib.h"

class MenuItem
{
  private:
    typedef void (*CallbackFunction)();
    CallbackFunction callback = NULL;
    String *_text;
  public:
    MenuItem();
    MenuItem(const MenuItem &obj);
    void draw();
    void update();
    void run();
    void setText(String txt);
    void attachHandler(CallbackFunction f);
    String getText();
};

#endif

Ответы [ 2 ]

0 голосов
/ 14 марта 2019

menuItem, переданная в функцию addMenuItem, является копией, которая имеет срок жизни до конца этой функции.

Попробуйте передать элемент меню в качестве справочного, чтобы ваш список пунктов менюбудет заполнен объектами, срок жизни которых больше, чем у функции addMenuItem.Это изменить подпись, чтобы выглядеть так:

void Menu::addMenuItem(MenuItem& menuItem)
0 голосов
/ 14 марта 2019

Когда вы вызываете std::vector::push_back, вы создаете копию своего объекта и сохраняете ее в векторе.Поэтому сначала проверьте конструктор копирования вашего класса и, если это может быть вызвано ошибкой.

Затем вам нужно знать, где хранится память, необходимая для std::vector.

На встроенной цели вы можете не использовать традиционную стандартную библиотеку, а манипулирование памятью может быть сложным.

Когда вы объявляете свой вектор как глобальную переменную, весьма вероятно, что требуемая память находится не в той же зоне, чем когда вы объявляете ее как закрытый член класса.Это будет зависеть от вашей платформы, компилятора, скрипта компоновщика и используемой вами библиотеки C ++.std::vector используйте распределитель, в Linux вы можете уйти, не глядя на то, что он делает, когда на встроенной цели вам нужно знать, какой распределитель вы используете и где находится память.

Вы можете попытаться напечататьадрес std::vector::data(), чтобы проверить это.Тогда вам, вероятно, придется либо предоставить свой собственный распределитель, либо зарезервировать часть памяти, достаточно большую, чтобы содержать вектор и инициализировать данные, содержащиеся в вашем векторе, по этому адресу памяти.

...