Passing References to pass the Reference... Again LOL [SOLVED]

Hey everyone, first post here. Been lurking for a good long time. Never posted anything before this because I can almost always find my own answers... but this time is a little different.

Anywho, I'm not new to Arduino and I'm fairly fluent, not professional, but fairly fluent with a good deal of programming languages. Problem with me, tho, is I have so many hobby's, I'm in a, "Jack of all trades, master of none," situation here.

I've also seen many many posts of people not formatting correctly and not posting all of their info. I've read the how to post but there is one significant problem with me posting ALL of my code... It's over 2800 lines long and spread between 12 files at the moment and AIN'T NONE OF YOU GONNA WANNA READ IT ALL HAHAHA.

Enough rambling tho, I feel like I can supply enough information to get the help I need without boring you all half-way to deafness. (I seem to have already rambled myself that far).


My current problem is I need to pass a reference to an object, which then constructs it's instance of an object using the reference. I'm really new to the object oriented side of programming as I had to switch to it after I ran into the spagetti factory with my last version. Got it running but wasted too much time... wasted too much time porting it to objects but I'm getting the knack and freaking love it (ramble ramble ramble).

I'll show the head of the object that was passed some references, and then move to the next object that is having a hard time with it.

Also, I'm not quite finished. Some how I managed to post before I could finish :frowning:

class APHandler {
  // this object creates an access point, generates a web page from a file
  // and gets client data to change to a new wifi router which this device
  //connects to

  private:
    //in this section, we create the reference variables/objects/structs
    //from the WiFi utilities

    WiFiClient &client;
    WiFiServer &server;
    int &pStatus;

    // object constructor for the Access point handler. We make
    // APHandler objects from the main object that runs all the
    // the other objects to form a system. It holds the physical
    // variables we need to access with WiFi client and server,
    // then update the status variable

    APHandler(WiFiClient &pClient, WiFiServer &pServer, int &pStatus) :
      client(pClient), server(pServer), status(pStatus)
    {
    }
    

    // You can pretty much ignore these for now as they aren't
    // related to my issue. Some are objects for ease of use,
    // others are global variables we can use for the
    // flash storage handler to keep settings if power is cycled

    const unsigned int apTimeOutDelay = 600000;
    
    char apSSID[31] = AP_SSID;
    char apPASS[63] = AP_PASS;

    String scanResults;
    String clientData;
    bool valid;

    MillisAlarm apTimer;
    MillisAlarm timeOut;


    // HERE IS WHERE THIS START BREAKING DOWN
    // the error I'm getting is client is not a type. The 
    // other error I'm getting is that the debugger is stating
    // the client reference I pass to my wifi connection
    // handler, is not a valid type when the library needs to
    // have the reference passed to it

    WiFiD disconnector(client, status);
    HTMLHandler htmlHandler(client, scanResults, clientData);
    URLParser urlParser(client, clientData);

    //... too much code to bore everyone to death with

}}}}

And here is the debugger info:

exit status 1
'client' is not a type

Finally, here is the code to the part the compiler is complaining about in the debugger:

class URLParser {
  // this object handles parsing the request information sent
  // from the device connected to the arduino in "AP" mode
  
  // below is where I take the reference and construct this
  // object out of it
  private:
    WiFiClient &client;
    String &clientData;
  
    URLParser(WiFiClient &pClient, String pClientData) :
      client(pClient), clientData(pClientData)
    {
    }

    // the rest of this is pretty much useless to everyone.
    // my errors only have to do with passing reference
    // included so you can see where I try to access information
    // provided at the address of the reference as a 
    //WiFiClient object/struct... not sure which
  
    const String replacementCodeTable = "~%7E!%21@%40#%23$%24^%5E=%3D:%3A;%3B?%3F,%2C";
    String temp = "   ";
    String t_SSID = "                               ";
    String t_PASS = "                                                               ";
    uint8_t inStr;
    
    ValidateString validate;

    void receiveURL(String &urlData) {
      
      //--------
      // here is where I start using the object.
      // it doesn't complain here, it complains in
      // the constructor
      //--------

      while (client.available()) {

Pointers and reference aren't my strong point but I've managed to get by till now.
If you know how to pass it forward with a reference to keep passing it forward, I would much appreciate the help!!!
Thanks!
Spencer

Posting a small, complete project might be better than posting a small, incomplete part of a large project. Can you make a small, complete, self-contained example of what you want to do that displays the same compiler errors?

Yeah, I can whip something up really quick... standby

Supernovali:
Hey everyone, first post here.

Nope again, LOL

OH MY GOODNESS!!! hahahaha i didn't know I posted bahaha

Ok, here is the requested code to demonstrate my meaning…

#include <WiFiNINA.h>


class Disconnector {  //third degree of sep. here
  WiFiClient &client;
  int &status;

  Disconnector(WiFiClient &pClient, int &pStatus) :
    client(pClient), status(pStatus)
  {
  }

  public:
    void disconnectAllWiFiModes() {
      
      //disconnect all types of connections
    }
    
};




class SecondDegreeOfSeparation_WiFiConnector {
  WiFiClient &client;
  int &status;

  bool ifWeNeedToDisconnect;

  SecondDegreeOfSeparation_WiFiConnector(WiFiClient &pClient, int &pStatus) :
    client(pClient), status(pStatus)
    //only need client and status for this
  {
  }

  Disconnector disconnector(client, status);

  public:
    void setup() {
      //do some setup for connector
    }

    void loop() {
      
      //send and receive data from network to some variable
      //i can't be bothered to try and replicate in this example
      
      //something should handle the variable in the following statement
      
      //if something goes wrong so we can reconnect
      if (weNeedToDisconnect) disconnector.disconnectAllWiFiModes();
      
    }
    
};



class SecondDegreeOfSeparation_AccessPoint {
  WiFiClient &client;
  WiFiServer &server;
  int &status;

  bool validSSID_PASS_received;

  SecondDegreeOfSeparation(WiFiClient &pClient, WiFiServer &pServer, int &pStatus) :
    client(pClient), server(pServer), status(pStatus)
  {
  }

  Disconnector disconnector(client, status);

  public:
    void setup() {
      
      //do something like make an Access Point
      
    }

    bool loop() {
      
      //do something like act on Access Point and get user credentials
      //so we can connect to a network

      //something should set validSSID_PASS_received for the following statement
      
      if (validSSID_PASS_received) {
        //valid credentials received
        disconnector.disconnectAllWiFiModes();
        return true;
      } else {
        return false;
      }
    }
    
};



class FirstDegreeOfSeparation_WiFiHandler {
  WiFiClient &client;
  WiFiServer &server;
  int &status;

  bool some_condition_like_firstRun = true;

  FirstDegreeOfSeparation(WiFiClient &pClient, WiFiServer &pServer, int &pStatus) :
    client(pClient), server(pServer), status(pStatus)
  {
  }

  SecondDegreeOfSeparation_AccessPoint    accessPoint(client, server, status);
  SecondDegreeOfSeparation_WiFiConnector  wifiConnector(client, status);


  public:
    void setup() {
      
      //setup up both access point and connector
      accessPoint.setup();
      wifiConnector.setup();
    }

    void loop() {
      
      //do something with the loops
      
      if (some_condition_like_firstRun) {
        some_condition_like_firstRun = accessPoint.loop();
      } else {
        //make it disconnect and reconnect to wifi
        wifiConnector.loop();
      }
    }
    
};



class MainObject {
  WiFiClient client;
  WiFiServer server(80);
  int status = WL_IDLE_STATUS;

  FirstDegreeOfSeparation_WiFiHandler wifiHandler(client, server, status);

  //setup some other classes

  public:
    void setup() {
      
      wifiHandler.setup();
      
      //setup some other classes
      
    }

    void loop() {
      
      wifiHandler.loop();
      
      //maintain some other classes
      //all my code is non blocking
    }
    
};




MainObject mainDoDad;

void setup() {
  mainDoDad.setup();
}

//run the non blocking code
void loop() {
  mainDoDad.loop();
}

And attached debug as text file…

debug.txt (9.92 KB)

I was hoping for a simple, generic example without all the WiFi stuff. Since your question doesn't seem related to WiFi. I have no idea what WiFiNINA does or what board it's used for. A simple MRE would be best.

I'm not sure how to construct an MRE out of the information I have because I'm not sure if it's an issue with objects, if it's an issue with the library or if I'm not understanding the use of passing a reference and then passing that reference again correctly.

The WiFiNiNA library is used for interfacing the arduino nano 33IoT WiFi module with the standard arduino wifi functions.

My objective is to have an object own the client, server, status variables and then pass the reference to the next object which may then pass it on to other objects. So I included that example and the debug file to try and figure out where my problem is.

Supernovali:
I'm not sure how to construct an MRE out of the information I have because I'm not sure if it's an issue with objects, if it's an issue with the library or if I'm not understanding the use of passing a reference and then passing that reference again correctly.

Then you need to divide and conquer. Separate your OOP / Reference issues from your library issues. Quite frankly, even your simplified example is too convoluted for me to deal with.

Regarding the passing down of references, is this what you mean?

class A {
  public:
    A(uint8_t &i) : ai(i) {
    }

    void print_A() {
      Serial.println(ai);
    }

  private:
    uint8_t &ai;
};

class B {
  public:
    B(uint8_t &i): a(i) {
    }

    void print_B() {
      a.print_A();
    }
  private:
    A a;
};

uint8_t x = 14;
B b(x);

void setup() {
  Serial.begin(115200);
  delay(1000);

  b.print_B();
  x = 100;
  b.print_B();
}

void loop() {
}

Output:

14
100

Yes, passing the reference of x to an instance of B, then passing it on to A so is able to print value of x, the reference contained, now, in ai. I didnt think it should matter who owns the variable, whether its global, if B owned it, passed it to A, who then passed it to C if there was a class C.

The error I'm getting is related to when I call the constructor for the next class with the arduino's wifi library. I declare WiFiClient as the variable type since client is of type WiFiClient. But it says that client "doesnt name a type."

I used the same declarations of data type as you did in your example, to call the pass to reference by type, in other words.

I can pass classes by reference, as in by composition. But this doesnt seem to work with data types of the WiFiClient. I can do it from functions to functions A-OK but just not by classes passing the variable by reference :frowning:

Supernovali:
The error I'm getting is related to when I call the constructor for the next class with the arduino's wifi library. I declare WiFiClient as the variable type since client is of type WiFiClient. But it says that client "doesnt name a type."

You're doing it incorrectly. See Case #2 and Case #3 here: When do we use Initializer List in C++? - GeeksforGeeks

Ok, I'll try something in a little but to see what happens. I noticed that the constructor was in the public section instead of private. I'll give that a shot.

You’re doing it incorrectly. See Case #2 and Case #3 here: When do we use Initializer List in C++? - GeeksforGeeks

I‚Äôve tried sever permutations of the example code and still get the same error when trying to compose the ‚ÄúFirstDegreeOfSeparation_WiFiHandler wifiHandler(client, server, status);‚ÄĚ class. :frowning: I used the examples from the link to try different methods of instantiation and can‚Äôt for the life of me figure out what it is im doing wrong.

The debugger points to that line of code. Here is the debugger output:

  FirstDegreeOfSeparation_WiFiHandler wifiHandler(client, server, status);

---

exit status 1
'client' is not a type

This is the code that it is a part of (I want the MainObject objects to own this so other parts of the program can use it in other parts):

class MainObject {
  WiFiClient client;
  WiFiServer server(80);
  int status;

  //setup some other classes

  FirstDegreeOfSeparation_WiFiHandler wifiHandler(client, server, status);

<...>
}

And here is the constructor and head of the class I’m trying to construct:

class FirstDegreeOfSeparation_WiFiHandler {
  WiFiClient &client;
  WiFiServer &server;
  int &status;

  bool some_condition_like_firstRun = true;

  FirstDegreeOfSeparation(WiFiClient &pClient, WiFiServer &pServer, int &pStatus) :
    client(pClient), server(pServer), status(pStatus)
  {
  }

  SecondDegreeOfSeparation_AccessPoint    accessPoint(client, server, status);
  SecondDegreeOfSeparation_WiFiConnector  wifiConnector(client, status);

<...>
}

You're still violating Case #3 at the link I supplied.

Ok, I tried the Case 3 method you described… and I got a new error. I don’t quite understand the link supplied because there is some confusion about what it means when it says:

If class A had both default and parameterized constructors, then Initializer List is not must if we want to initialize ‚Äúa‚ÄĚ using default constructor, but it is must to initialize ‚Äúa‚ÄĚ using parameterized constructor.

‚Äú‚Ķthen Initializer List is not must‚Ķ‚ÄĚ and then again when he says, ‚Äú‚Ķbut it is must to initialize‚Ķ‚ÄĚ I‚Äôm not quite sure what he‚Äôs saying at these two points.

Anywho, here is the modified code broken down into a much smaller chunk because I’ve identified that it doesn’t matter how many times the reference is passed, just that the constructor is trying to pass by reference, period:

#include <WiFiNINA.h>


class WiFiHandler {
  private:
    WiFiClient &client;
    int &status;
    
  public:
    WiFiHandler(WiFiClient &, int &);
  
    void setup() {
      //do wifi setup
    }

    void loop() {
      //do wifi loop
    }
    
};

WiFiHandler::WiFiHandler(WiFiClient &pClient, int &pStatus) {
  client = pClient;
  status = pStatus;
}


class MainObject {
  private:
    WiFiClient client;
    WiFiServer server(80);
    int status = WL_IDLE_STATUS;

    WiFiHandler wifiHandler(client, status);

  public:
    void setup() {
      wifiHandler.setup();
      //do MainObject setup
    }
    
    void loop() {
      wifiHandler.loop();
      //do MainObject loop
    }

};


MainObject mainDoDad;


void setup() {
  mainDoDad.setup();
}

void loop() {
    mainDoDad.loop();
}

And here is debug:

H:\ArduinoIDEPortable\arduino-1.8.13\Portable\sketchbook\referenceToReferenceToReference_help3\referenceToReferenceToReference_help3.ino: In constructor 'WiFiHandler::WiFiHandler(WiFiClient&, int&)':
referenceToReferenceToReference_help3:22:1: error: uninitialized reference member in 'class WiFiClient&' [-fpermissive]
 WiFiHandler::WiFiHandler(WiFiClient &pClient, int &pStatus) {
 ^~~~~~~~~~~
H:\ArduinoIDEPortable\arduino-1.8.13\Portable\sketchbook\referenceToReferenceToReference_help3\referenceToReferenceToReference_help3.ino:6:17: note: 'WiFiClient& WiFiHandler::client' should be initialized
     WiFiClient &client;
                 ^~~~~~
referenceToReferenceToReference_help3:22:1: error: uninitialized reference member in 'int&' [-fpermissive]
 WiFiHandler::WiFiHandler(WiFiClient &pClient, int &pStatus) {
 ^~~~~~~~~~~
H:\ArduinoIDEPortable\arduino-1.8.13\Portable\sketchbook\referenceToReferenceToReference_help3\referenceToReferenceToReference_help3.ino:7:10: note: 'int& WiFiHandler::status' should be initialized
     int &status;
          ^~~~~~
H:\ArduinoIDEPortable\arduino-1.8.13\Portable\sketchbook\referenceToReferenceToReference_help3\referenceToReferenceToReference_help3.ino: At global scope:
referenceToReferenceToReference_help3:31:23: error: expected identifier before numeric constant
     WiFiServer server(80);
                       ^~
referenceToReferenceToReference_help3:31:23: error: expected ',' or '...' before numeric constant
referenceToReferenceToReference_help3:34:29: error: 'client' is not a type
     WiFiHandler wifiHandler(client, status);
                             ^~~~~~
referenceToReferenceToReference_help3:34:37: error: 'status' is not a type
     WiFiHandler wifiHandler(client, status);
                                     ^~~~~~
H:\ArduinoIDEPortable\arduino-1.8.13\Portable\sketchbook\referenceToReferenceToReference_help3\referenceToReferenceToReference_help3.ino: In member function 'void MainObject::setup()':
referenceToReferenceToReference_help3:38:7: error: invalid use of member function 'WiFiHandler MainObject::wifiHandler(int, int)' (did you forget the '()' ?)
       wifiHandler.setup();
       ^~~~~~~~~~~
referenceToReferenceToReference_help3:38:7: error: invalid use of member function 'WiFiHandler MainObject::wifiHandler(int, int)' (did you forget the '()' ?)
H:\ArduinoIDEPortable\arduino-1.8.13\Portable\sketchbook\referenceToReferenceToReference_help3\referenceToReferenceToReference_help3.ino: In member function 'void MainObject::loop()':
referenceToReferenceToReference_help3:43:7: error: invalid use of member function 'WiFiHandler MainObject::wifiHandler(int, int)' (did you forget the '()' ?)
       wifiHandler.loop();
       ^~~~~~~~~~~
referenceToReferenceToReference_help3:43:7: error: invalid use of member function 'WiFiHandler MainObject::wifiHandler(int, int)' (did you forget the '()' ?)
exit status 1
uninitialized reference member in 'class WiFiClient&' [-fpermissive]

Thanks for putting up with my learning experience!
Spencer

P.S. I‚Äôve identified, throught the debugger with new errors, that WiFiClient is indeed a class so saying ‚ÄėWiFiClient client‚Äô constructs member ‚Äėclient‚Äô as class WiFiClient.

Perhaps a look at how this fellow does a thing:
pubsubclient/PubSubClient.cpp at master · knolleary/pubsubclient · GitHub. The PubsubCLient takes as an input parameter a WiFI object.

Ok, I have a semi-solution, but it breaks the purpose of classes having ownership of their variables... I guess it will have to do for now, but some help would be awesome in figuring this problem out.

The solution I have right now is to declare the variables I'm trying to pass by reference be global variables :frowning:

Perhaps a look at how this fellow does a thing:
pubsubclient/PubSubClient.cpp at master · knolleary/pubsubclient · GitHub. The PubsubCLient takes as an input parameter a WiFI object.

Wanna know something funny??? I was trying to use PubSubClient for this very project I'm needing help with and settles with Adafruit_MQTT BAHAHA. I've looked over this code before!!! hahaha

I'll take a closer looking into it and see how he manages the passes :slight_smile:

Thanks for the pointers (no pun intended... actually, it kind of turned into a pun HAHAHA)

Thanks!!!

Looking at people’s usage of PubSubClient, it appears that everything is done on the global scope as well… Correct me if I’m wrong, if my MainObject class is declared on the global scope and therefore has no implicit destruction, any classes declared within my MainObject class’ constructor, should remain in the scope of any object made from MainObject class, right???

class SomeClass {
  <...>//arbitrary code for the class
};


class MainObject {
  SomeClass someClass;
  //MainObject gets declared globally below, and since someClass
  //gets constructed from a class that has no implicit destructor
  //if should also have no implicit destructor, right?

  <...>//arbitrary code
};


MainObject mainDoDad;
//mainDoDad declared globally, so no implied destructor ever called


void setup() {
  mainDoDad.setup();
}

void loop() {
  mainDoDad.loop();
}

Ok. Been building from the ground up to the sky‚Ķ I get stuck really quick. Now I‚Äôm just trying to pass reference to something simple like the status (int) and I can‚Äôt get past that. (int)status should be constructed when the constructor for the class calls ‚ÄúMainObject mainDoDad;‚ÄĚ But for some reason, it says status is not a type.

Here is the code and the debug:

#include <WiFiNINA.h>


class WiFiHandler {
  int &status;

  WiFiHandler(int &pStatus) :
    status(pStatus)
  {
  }

  public:
    void setup() {
      
    }

    void loop() {
      
    }
    
};


class MainObject {
  int status = WL_IDLE_STATUS;

  WiFiHandler wifiHandler(status);

  public:
    void setup() {
      wifiHandler.setup();
    }

    void loop() {
      wifiHandler.loop();
    }
    
};


MainObject mainDoDad;


void setup() {
  mainDoDad.setup();
}

void loop() {
  mainDoDad.loop();
}

referenceToReferenceToReference_helpRebuild:27:27: error: 'status' is not a type
   WiFiHandler wifiHandler(status);
                           ^~~~~~
H:\ArduinoIDEPortable\arduino-1.8.13\Portable\sketchbook\referenceToReferenceToReference_helpRebuild\referenceToReferenceToReference_helpRebuild.ino: In member function 'void MainObject::setup()':
referenceToReferenceToReference_helpRebuild:31:7: error: invalid use of member function 'WiFiHandler MainObject::wifiHandler(int)' (did you forget the '()' ?)
       wifiHandler.setup();
       ^~~~~~~~~~~
referenceToReferenceToReference_helpRebuild:31:7: error: invalid use of member function 'WiFiHandler MainObject::wifiHandler(int)' (did you forget the '()' ?)
H:\ArduinoIDEPortable\arduino-1.8.13\Portable\sketchbook\referenceToReferenceToReference_helpRebuild\referenceToReferenceToReference_helpRebuild.ino: In member function 'void MainObject::loop()':
referenceToReferenceToReference_helpRebuild:35:7: error: invalid use of member function 'WiFiHandler MainObject::wifiHandler(int)' (did you forget the '()' ?)
       wifiHandler.loop();
       ^~~~~~~~~~~
referenceToReferenceToReference_helpRebuild:35:7: error: invalid use of member function 'WiFiHandler MainObject::wifiHandler(int)' (did you forget the '()' ?)
exit status 1
'status' is not a type