5

I'm having some programming problems.

So here's what's happening:

In my .ino file, I have a tft variable which holds the connection to a LCD. I want to make a class which can either automatically access that tft class contained in the .ino, or pass it into the constructor when it's created; so basically:

// assuming this is the .ino:

TFT_ILI9163C tft = TFT_ILI9163C(cs, dc, rst);


MenuClass *menu = MenuClass();
menu->init("Example", tft); // this should work and "menu" should now have access to the "tft" variable

Here's my Menu.cpp:

// Menu class

#include "Menu.h"
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <TFT_ILI9163C.h>

String menName = "Unnamed";

void MenuClass::init(const String name) 
{
    menName = name;
}

String MenuClass::getName() {
    return menName;
}

void MenuClass::draw() {
    tft.setCursor(2, 2);
    tft.print(menName);
}

MenuClass Menu;
2

Assuming you want to require every instance of MenuClass should be associated with a TFT_ILI9163C display object, you could use something like this:

// MenuClass.h

class TFT_ILI9163C; // declare a class name which is defined in TFT_ILI9163C.h

class MenuClass
{
  private:
    // read-only private member initialized by constructor
    // (the m_ prefix is commonly used to denote class member values)
    TFT_ILI9163C* m_tft;

  public:
    // constructor
    MenuClass(TFT_ILI9163C* pTft) : m_tft(pTft) {};

  private:
    // private storage for the Name property
    String m_Name;
  public:
    // read the Name property
    String getName() {
      return m_Name;
    };
  public:
    // write the Name property
    void setName(String value) {
      m_Name = value;
    };

  public:
    void draw() {
      // the m_tft member is a reference to the display class
      m_tft->setCursor(2, 2);
      m_tft->print(m_Name);
    };
}
MenuClass Menu;

Note that there is only one constructor, and it requires a pointer to the TFT_ILI9163C display. The body of the constructor : m_tft(pTft) {}; initializes the private member m_tft with the constructor argument pTft, so MenuClass member functions invoke TFT functions as m_tft->fn(args); Since there is no "void constructor" MenuClass(void), m_tft is effectively guaranteed to point to a valid TFT_ILI9163C instance.

Since it looks like you were using menName kind of like a class property, I rewrote that in the more commonly used m_propertyname style. Your MenuClass::init() was behaving like a name property setter; I'm not sure whether menu initialization requires anything else. This simple example has class MenuClass defined entirely inside the header file.

Usage is pretty similar to your example code, except now the MenuClass constructor requires a pointer to a previously constructed TFT_ILI9163C display instance:

// Main application
#include <TFT_ILI9163C.h>
#include "MenuClass.h"
// ... etc ...

// the TFT_ILI9163C display instance
TFT_ILI9163C tft = TFT_ILI9163C(cs, dc, rst);

// an example menu that draws on the display
MenuClass *menuFoo = new MenuClass(&tft); // use new to get pointer to new class instance
// MenuClass *menuFoo = MenuClass(&tft); // cannot convert 'MenuClass' to 'MenuClass*' in initialization

void setup() {
  // an example menu that draws on the display
  menuFoo->setName("Example");
  menuFoo->draw();
}

If you wanted to pass the constructor an initial Name property value as well as the tft display pointer, you could define the constructor as

  public:
    // constructor
    MenuClass(TFT_ILI9163C* pTft, String name) : m_tft(pTft), m_Name(name) {};

You could even go a step further, and give the name argument a default value:

  public:
    // constructor
    MenuClass(TFT_ILI9163C* pTft, String name = "Unnamed") : m_tft(pTft), m_Name(name) {};

So with this modification, the expression MenuClass(&myTFT) is the same as the expression MenuClass(&myTFT, "Unnamed"), but you can still override the default value like MenuClass(&myTFT, "DoSomething").

It is also perfectly legal to put statements inside the { } block of the constructor, but in this example all of the work is accomplished by the :memberName(value) constructor syntax.

Edit: MenuClass *menuFoo = new MenuClass(&tft); thanks @BrettAM

  • MenuClass *menuFoo = MenuClass(&tft); looks fishy to me, does that actually compile? It looks like you mean MenuClass menuFoo(&tft); or MenuClass *menuFoo = new MenuClass(&tft); – BrettAM Dec 24 '15 at 23:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.