Arduino hangs on virtual method

NickAmSee:
handleTouch in the setup method is working - in loop it is crashing

first glance?

maybe because of this:

void setup() {
  Serial.begin(9600);
  Button button1=Button("A");
  Serial.println("Button1 created");
  gui.addElement(&button1);
  Serial.println("Button1 added");
  
  
  Button button2=Button("B");
  Serial.println("Button2 created");
  gui.addElement(&button2);
  Serial.println("Button2 added");
  
  gui.handleTouch(1,1);
  Serial.println("Touch handled setup");
}

see anything there...?

hint: what scope are your Button objects?

NickAmSee:
Now it's getting interesting.

a couple of other notes:

you don't need the this-> to access class members within the class:

this->controlElements[elementCount]=controlElement;

just:

controlElements[elementCount]=controlElement;

this:

Button button2=Button("B");
  • creates an instance of Button class
  • copy's that instance to button2
  • deletes the first instance created

so just:

Button button2("B");

instead of this:

ControlElement(String id){
      this->id=id;  
    }

you can initialize a class in C++ using initializers... but don't get your variable names mixed.

ControlElement(String someId) : id(someId){} // initializes id to the argument someId

and finallly:

String id;

nix the String class.

BulldogLowell:
yes... If you take out the getArea() method from the Circle class in the example... compiler complains:

cannot declare variable 'circle' to be of abstract type 'Circle'

or in other words "you've inherited a pure virtual function and you haven't defined it, you big dope"

PaulS:
I want to make sure that I have this straight. The virtual keyword, without the =0, says that a derived class CAN override the method, but does not have to, while the virtual keyword, with the =0, says that a derived class MUST implement the method. Is that right?

If you have this in your base class 'virtual int handleTouch(int x,int y)=0;' then what bulldoglowell says is the case - you MUST implement that function in your derived classes.

But as is generally the case with C++ there are other options.

You could just implement an empty function in your base class:

virtual int handleTouch(int x,int y)
{
    return 0;
}

And then your derived classes can override this function if they need to.

Not sure doing this is of any value in your case.

Perhaps if you wanted to include a bit of debugging:

virtual int BaseClass::handleTouch(int x,int y)
{
    Serial.println(x);
    Serial.println(x);
    return 0;
}

virtual int DerivedClass::handleTouch(int x,int y)
{
    BaseClass::handleTouch(x, y);
    .
    .
    .
    .
    return 0;
}

NickAmSee:
As I’m not too deep into C++ a short Java Example what was mit Original intent:

public abstract class ControlElement{
 public abstract int handleTouch(int x,int);

}
public class Button extrends ControlElement{
public int handleTouch(int x,int y){

}

ControlElement controlElements=new ControlElement[10];

controlElements[0]=new Button(…);

controlElements[0].handleTouch(…);

This example is C# (sharp)

And C# does not have pointers like C++ does.

So ‘ControlElement controlElements=new ControlElement[10];’ does not mean the same thing in C++.

In C++ this would be ControlElement controlElements[10]; and it literally means an array of objects created from your base class with that pure virtual function.

You have to do it this way in C++ if you want the virtual function polymorphism to kick in.

ControlElement* controlElements = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};

or

ControlElement* controlElements[10];
memset(controlElements, NULL, 10);

Then you need to create objects from your derived class and put pointers to them (&button / address of button) into your controlElements array.

This might help - it is an array of pointers to float values but the idea is the same.

Here is some basic code to setup your control container - not checked for compile errors.

I have speculated as to your requirements but it should give you a start at least.

class CControlElement
{
  protected:
    int m_nTopLeftX, m_nTopLefty;
	
  private:
    // Empty constructor.
	// Making this private prevents it from being called unintentionally - all control elements require a position on the screen.
	// If it gets called then a compile error will be generated and you will need to provide two parameters so this constructor is called instead: CControlElement(const int nTopLeftX, const int nTopLeftY)
	CControlElement()
	{
	  m_nTopLeftX = m_nTopLefty = 0
	};
  
  public:
    // Constructors
	CControlElement(const int nTopLeftX, const int nTopLeftY)
	{
	  m_nTopLeftX = nTopLeftX;
	  m_nTopLefty = nTopLeftY;
	};
	virtual in handleTouch(const int nX, const int nY) = 0;
};

class CButton: public CControlElement
{
  private:
    // Empty constructor.
	// Making this private prevents it from being called unintentionally - all buttons require a position on the screen.
	// If it gets called then a compile error will be generated and you will need to provide two parameters so this constructor is called instead: CButton(const int nTopLeftX, const int nTopLeftY)
	CButton()
	{
	};
  
  public:
    // Constructors
	CButton(const int nTopLeftX, const int nTopLeftY): CControlElement(nTopLeftX, nTopLeftY)// Pass the parameters of CButton(...) to the correct constructor from the base class.
	{
	};
	virtual in handleTouch(const int nX, const int nY)
	{
	    .....
	};
};

class CControlElements
{
  protected:
    CControlElement* m_arrayControlElements[10];
	int m_nCurrentSize;
	CButton m_button1, m_button2;
	
  public:
    // Constructor
    CControlElements()
	{
		m_arrayControlElements[m_nCurrentSize++] = &m_button1;
		m_arrayControlElements[m_nCurrentSize++] = &m_button2;
	};
	
	CControlElement* getControlElement(const int nNumber)
	{
	  if ((nNumber >= 0) && (nNumber < m_nCurrentSize))
		return m_arrayControlElements[nNumber];
	  return NULL;
	}
	
	int handleTouch(const int nX, const int nY)
	{
	  int nResult = 0;
	  
	  for (int nI = 0; nI < m_nCurrentSize; nI++)
	  {
	    nResult = m_arrayControlElements[nI].handleTouch(nX, nY);
	    if (nResult > 0) // Touch handled
		  break; // Break out of for loop.
	  }
	  return nResult;
	}
};

boylesg:
This example is C# (sharp)

did you miss OP's code in post 19?

BulldogLowell:
did you miss OP's code in post 19?

The OP can add in the other bits from his original code if he finds my sample code useful.

Oh... local definition. This was the reason..... Working now Thx