2

I wish to access methods and fields, as well as change them, of class A from class B. Since the main Arduino sketch is not a class, but a list of fields and methods, I created a separate MainClass with a method printStuff() that I want to call from class DoClass. This is how I go about it:

The main sketch:

#include "MainClass.h"
MainClass m;
void setup() {
  m.setup();
}
void loop() {
  m.loop();
}

MainClass.h:

/*
  MainClass.h
*/
#ifndef MainClass_h
#define MainClass_h
#include "Arduino.h"
class MainClass
{
  public:
    MainClass();
    void setup();
    void loop();
    void printStuff();
};
#endif

MainClass.cpp:

/*
  MainClass.cpp
*/

#include "Arduino.h"
#include "MainClass.h"
#include "DoClass.h"
MainClass::MainClass()
{
  d DoClass(this);
}
void MainClass::setup(){
  Serial.begin(9600);
}
void MainClass::loop(){
  d.callMainClassFunct();
}
void MainClass::printStuff(){
  Serial.println("printing stuff");
}

DoClass.h:

/*
  DoClass.h
*/
#ifndef DoClass_h
#define DoClass_h

#include "Arduino.h"
#include "MainClass.h"
class DoClass
{
  public:
    DoClass(MainClass m);
    void callMainClassFunct();
  private:
    MainClass _m;
};
#endif

DoClass.cpp:

/*
  DoClass.cpp
*/

#include "Arduino.h"
#include "MainClass.h"
#include "DoClass.h"

DoClass::DoClass(MainClass m)
{
  _m = m;
}

void DoClass::callMainClassFunct(){
  _m.printStuff();
}

This produces a myriad of errors. Each time I change something, a new kind of error appears, as though I was in a vicious cycle. Clearly, I am unfamiliar with C++. It would greatly help me if you could alter my code so that it works, keeping in mind that I would like to both access methods and fields of class MainClass from class DoClass and change those fields from class DoClass.

For reference, in Java, I would achieve the same in the following way:

MainClass.java:

public class MainClass{
    DoClass d;

    public MainClass(){
        d = new DoClass(this);
}

    public void setup(){

}

public void loop(){
    d.callMainClassFunct();
}

public void printStuff(){
    Serial.println("print stuff");
}

}

DoClass.java:

public class DoClass{
       MainClass _m;
       public DoClass(MainClass m){
          _m = m;
       }
       public callMainClassFunct(){
         _m.printStuff();
}

}

Passing this to the constructor od DoClass passes the value of the reference pointing to MainClass instantitated in the main sketch file. Then, by prepending the name of the instantiated object (in this case, "m"), followed by a dot, I can simply access and change all values of that object from DoClass (provided those methods and fields are visible to DoClass, which is the case here).

I have posted before about this issue, but did not receive any answers to my specific question and could not comment because I do not have enough reputation. Thank you to those who tried to answer me, but the answers did not pertain to my specific question. This time I have included more information to show my problem more clearly. Thank you in advance for your help.

  • Why are you putting the whole sketch inside a class? This is like shoehorning a Java paradigm into C++. Why don't you ask about the actual problem you want to solve, instead of asking for help in following your misguided attempt at transforming C++ into Java? – Edgar Bonet Jun 29 '16 at 12:20
  • I am trying to create a program, which performs various tasks. Each class executes a task: in loop(), I call task1.loop(), task2.loop() etc. depending on the state of the program. Those classes need to respond to the main sketch to update the state of the program based on their completion. I haven't found a way to reference any fields or methods from the main sketch, so I created a MainClass, which would then be passed to those tasks to create aliases and access MainClass. The example that I gave is just a proof of concept - to see if I can reuse a very handy schematic from past Java projects. – wit221 Jun 29 '16 at 12:41
1

In your Java version, you define MainClass like this (my comments added):

public class MainClass{ // Define a new Class
    DoClass d;          // Add a member variable to the class
    public MainClass(){
        d = new DoClass(this); // Initialise the member variable
    } // MainClass()
} // MainClass

In your C++ you don't do the same thing - but you should! The class needs a DoClass member so that you can use it in other MainClass functions:

// MainClass.h
...
#include "DoClass.h" // Need the .h here - remove it from the .cpp
class MainClass
{
  public:
    MainClass();
    void setup();
    void loop();
    void printStuff();
  private:
    DoClass _d; // Create a private member variable to use
};

and

// MainClass.cpp
MainClass::MainClass() : // MainClass constructor (note colon)
           _d(*this) // Initialise member
{
} // MainClass::MainClass()

Now, you want DoClass to be able to use MainClass, so you passed it into DoClass's constructor. But DoClass cannot have a MainClass inside it - MainClass already has a DoClass inside it! Infinite impossibility! So you need DoClass to merely contain a reference to the MainClass that it sits inside. That's the C++ unary & operator (different from the binary & operator), which is used similar to the pointer * operator:

// DoClass.h
...
// Need to advise compiler MainClass exists...
// but can't #include MainClass.h! Infinite loop!
class MainClass;

class DoClass
{
public:
    DoClass(MainClass &m); // Reference to MainClass
    void callMainClassFunct();
private:
    MainClass &_m; // Reference to MainClass
};

and

// DoClass.cpp
DoClass::DoClass(MainClass &m) : // DoClass constructor - note colon
         _m(m) // Initialise member variable
{
}

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.