Changing a variable in ofApp from a child class?


#1

Hi.

Ive been struggling… how do I access/update a var in ofApp from a child class method? My code so far below…

ofApp:

int variable;    //change this var

childClass child;

void ofApp::setup(){
   child.setup();
}

void ofApp::update(){
   child.update();
}

void ofApp::draw(){
   child.draw();
}

childClass:

class childClass {
}

void childClass::setup(){
}

void childClass::update(){
}

void childClass::draw(){
}

void childClass::customMethod(){
   //change variable from here
}

#2

I haven’t had the chance to try this solution, but it should work.

Firstly you need to declare “variable” in ofApp.h so that it becomes a member variable of ofApp. Then in childclass::setup() (or whatever method) just do:

auto ptrToApp = dynamic_cast<ofApp*>(ofGetAppPtr()); 
ptrToApp->variable = 42;

remember to include ofApp.h in childclass.cpp, good luck!


#3

Thanks @Wiklund but I am getting a ton of errors on this. I am using oF iOS not sure of that is an issue.

I did as you mentioned:

  • included ofApp.h in childclass.cpp
  • declared the variable in ofApp.h
  • added the lines above in Childclass setup()

My log:

Thanks for your help.


#4

That’s strange, I’ve had the chance to try it out now and it works on iOS on my end. However, I do remember running into the same error message on another ofIOS app a couple of years ago. I remember getting around the issue by changing the filename of childClass.cpp to childClass.mm (and thus making it an Objective cpp class). The error about NSString not being found is related to Objective-C since NSString is the standard string type in Objective-C, so making Xcode beleive that your class is an Objective-C related object may do the trick. This thread explains it better and provides an alternative solution

Your original problem with accessing “variable” can be solved in a different way though. Simply making your top level app object a singleton would make your code cleaner and more readable. ofGetAppPtr() actually returns a singleton of your ofBaseApp object, so why not make the object you actually want to work with a singleton and skip the dynamic_cast shenanigans? Google c++ singleton for more alternatives if this is new territory for you, but here is roughly how I do it:

ofApp.h:

class ofApp
{
public:
  //lots of other methods, update() etc.....

  static ofApp& getInstance()
  {
    return *pApp; 
  }

private:
  static ofApp* pApp;
};

Next: In ofApp.cpp just below your #includes (outside of any method)

ofApp* ofApp::pApp = 0;

And still in ofApp.cpp inside the constructor:

ofApp::ofApp( )
{
    pApp = this;    
}

ofApp is now a singleton and all you need to do to solve your original problem is:

  1. Declare “variable” in ofApp.h (already done, right?)
  2. Include ofApp.h in childClass.cpp
  3. In childClass.cpp do this:

void childClass::customMethod()
{
ofApp& myApp = ofApp::getInstance();
myApp.variable = 42;
}

This is the exact same thing you tried to do in my last example, but now you’re getting an instance of the ofApp object instead of the ofBaseApp object that ofGetAppPtr() gives you. And hopefully this will result in less compiler errors as well.

Rant:
If this is your first encounter with singletons be aware that some devs hate them and even consider them an “anti pattern”. I find that position rather strange since singletons are a part of most app platforms (iOS and Android apps use them) and if not overused they help you a lot. My opinion is to use them scarcely, one for your app object is probably enough.
Singletons can get you in a ton of trouble if you overuse them and subsystems, threads and other apps depend on one single instance of your app. So if your app is supposed to serve other apps with data (state in particular) think twice before implementing a singleton pattern.
End of rant.

Just give me a holler if the examples I provided fail or if there’s anything else that was unclear.


#5

Why not using dependency injection?


here is another thread about it:


#6

Thank you so much for your reply. Changing the extension to .mm from .cpp did the trick. I can now edit variables and call methods in ofApp from my class. Thank you. As for singletons, I will look at them a bit better and get back to you if I have any questions. Thank you again!