Virtual functions not working, cannot call base-class or derived-class functions

Hello all, I have been wracking my brain trying to fix this and I'm not sure if it's a big or a little problem. So what I'm trying to make is a User Interface for a 16x4 LCD. The main class has a 2-dimensional Array of pointers to the base class, UIElement. A derived class UITextElement overrides the functions of UIElement and introduces a few new ones.

My main problem is that I can't seem to get anything out of even my base-class. If I try to read a variable from it I simply get nothing.

here are some snippets (All files have include guards I am simply leaving them out to be brief)

FILE: UIElement.h

#include Arduino.h
class UIElement
{
public://allows any class in the project to manipulate it
  UIElement();
  virtual String updateLCD(); //may need to be virtual
};

FILE: UIElement.cpp

#include "UIElement.h"
UIElement::UIElement() 
{
}
String UIElement:: updateLCD()
{
  return "butts";
}

FILE: Main.ino

#include "UIElement.h"
UIElement *elementPtr[4][4];
void setup()
{
   UIElement shiz = UIElement();
   print(shiz.updateLCD());
   elementPtr[0][0] = &shiz;
   print(elementPtr->updateLCD();
}

So my problem is that neither print statement produces any output (the print statements are functions connected via LiquidCrystal. They do print other strings, but seem to get nothing out of the functions in my classes.) Does this look like it should work? Am I making a horrible mistake? Any feedback would be great, if you guys need more code out of me just say so I just didn't want to bombard you all with walls of text.

Where is your arduino code, the one that has the setup() and loop() functions?

... here are some snippets ...

Which will be welcome at http://snippets-r-us.com/.

Please at least upload compilable code that demonstrate the problem, preferably without us having to own your LCD.

Just demonstrate using Serial. But include enough to make the point.

If you use multiple files, zip them up into one, and include that as an attachment to your post.

edit -> removed this code as it isn't helpful, see followup for .zip

Sorry I posted before seeing your suggestion nick, give me a minute and I'll rewrite a quick example

Here is a small(ish) sketch which will output to Serial once a second. It will also attempt to call UIScreen.update() which should print out a String returned by my derived-class.

This example shows that the calls the the derived class does not produce any output. Any help would be greatly appreciated and thanks Nick for guiding me to this clearer way to present my problem. There is a lot of unused code but the update() function is all that really matters in the UIScreen.

UIProblem.zip (4.5 KB)

elementPtr is an array
Also I think you need to call something to do the printing
So instead of

print(elementPtr->updateLCD();

You need something like

 Serial.print(elementPtr[0][0]->updateLCD());

Well, I'm confused. For one thing:

String UIElement:: updateLCD()
{
  return "butts";
}

That isn't updating anything. It's returning a string.

I advise against using the String class, which I see you are doing a lot.

UIScreen::UIScreen(int row, int col)
{

  //lcd.begin(row, col); 
  //lcd.clear();
  numberOfScreens = 4;
  //Serial.begin(9600);
  /*
  UIElement tmpElement;
  setElement(tmpElement,0,0);
  */
  for (int i = 0; i <4; i++)
  {
     for (int j = 0; j < 4; j++)
    {
       elementPtr[i][j] = new UIElement;
    } 
  }
}

I'm not sure about doing that in the constructor.

Also, you are doing a new of UIElement not UITextElement.

What I suggest you do is throw in a whole lot of debugging prints. Particularly in the constructors and the display methods. That way you'll see what is going on.

Hmm, I seemed to find an unrelated error. The for loop in UIScreen.update() was never initialized it to zerp so it never actually performed any of the code within it's body (D'oh!). I also moved the initialization out of the constructor into it's own function init().

The best part is that it works!

I was returning Strings instead of actually updating within the function call mostly because I didn't want to send each function it's own reference to the LCD. That way they return the String which is then actually updated by the calling class. Are you saying to avoid String just because it is a fairly large data type or is there more to it?

Also I am initializing them all as new UIElement because the Pointer points to the base-class, when I then replace it with an actual derived-class object it will still be able to store it since they are derived but will call the derived functions instead of the base-class.

Here is a worry though, When I populate the array in UIScreen.init() I give each elementPtr a new UIElement, and when I actually use them I replace them with a UITextElement or in the future another derived class. Will the original object of UIElement still exist as a Memory Leak? I am coming from java where once an object isn't referenced anymore it is deleted by the garbage collector, I'm not sure if here it will just persist somewhere in memory or disappear. This is honestly more curiosity than worry, When the actual menu system is complete there will be no need to populate it with one then the other, simply populating them each with the derived class.

Thank you for your help though. I have uploaded my "fixed" code which prints out

4 rows, first is derived, rest are base-class
hello
butts
butts
butts

UIProblem.zip (4.51 KB)

I am coming from java where once an object isn't referenced anymore it is deleted by the garbage collector, ...

There is no garbage-collector, what you are doing looks dodgy.

I'm only populating the array with throw away objects for this examples sake, In the future It will be populated with the actual object that it will point to for the entire projects life. I will have to read up on how to deallocate memory or delete those objects before replacing them with my new ones in case that comes up though. I rented a C++ book from my library and its quite a steep learning curve. Thanks to all of you for commenting though, I think I'm at a decent stage to progress.

I'm only populating the array with throw away objects for this examples sake ...

Why bother? You don't have to put anything there.