views:

145

answers:

7

Hi guys,

I need to call properties and functions of an object from a different class.

The idea is passing 'this' as a parameter to the other class constructor. E.g.:

instance = ClassName(this);

And then do:

ParentClass parentInstance;
ClassName::ClassName(MainApp _instance){
    parentInstance = _instance;
}

However, my compiler says that ParentClass does not name a type. Ideas? Also, should I use a pointer to save memory? How?

Thanks in advance.


UPDATE:

Ok, sorry for the delay. Here it goes the actual code. First, a simple class.

Game class:

Header file

#ifndef _GAME
#define _GAME

#include "ofMain.h"

class Game{

 public:
  Game();
  ~Game();

  void hi();
};

#endif

cpp file:

#include "Game.h"
Game::Game(){}
Game::~Game(){}

void Game::hi(){ 
cout << "hi, I'm game! " << endl;
}

Then, from MainApp I create the object: - Relevant code on header file:

#ifndef _MAIN_APP
#define _MAIN_APP

#include "ofMain.h"
#include "Game.h"

class MainApp : public ofSimpleApp{
 public:
  Game game;
};

#endif

Relevant code on the cpp file:

game = Game();
game.hi();

This obviously works as I'm only creating a bloody object. However, problem comes with composition.

I could pass the main app as argument in the constructor, I could pass it via game.setParent(this);... problem is, I can't even define the variable to store the reference to the app.

E.g.: (making it easy/inefficient without pointers or anything)

Game.h:

#define _GAME
#ifndef _GAME

#include "ofMain.h"
#include "MainApp.h"

class Game{
 MainApp app;

 public:
  Game();
  ~Game();

  void hi();
 };
#endif

This returns a "does not name a type" error and declaring class MainApp returns an "incomplete type" error

I'm sure I'm doing something dumb.


UPDATE 2:

The problem with that method is that I can't call a function of the pointed object now.

This is Game.h:

#ifndef _GAME
#define _GAME

#include "ofMain.h"

class MainApp;
class Game{


 public:
  Game();
  Game(MainApp* _app);
  ~Game();

  void hi();

  MainApp* app;
};

#endif

As you see, app (of the type MainApp) is passed as a parameter. That's fine, MainApp exists as it's the forward declaration. However, when I try to call any of app's functions I can't (compiler error saying Request for member appHi in .... which is non-class type 'MainApp'.

MainApp is NOT included in Game.h but Game.h IS included in MainApp.h.

Ideas?

A: 

That's not how things work in C++. Unlike javascript, you cannot inject methods or fields into existing objects at runtime.

tdammers
I don't want to inject them, just call them.E.g.: parentInstance.draw();
ozke
A: 

It's called composition and is a common pattern. It's highly efficient in both semantics and in terms of runtime speed/memory footprint.

Your code example is a little too much pseudocode for me to read it correctly. Let me show you how it's done.

class X;
class Y {
    ...
    void DoSomething(X* x, ... args);
};
class X {
    Y y;
    void DoSomething() {
        y.DoSomething(this, args);
    }
};
DeadMG
I tried that but it says y has incomplete type. Y is defined in a different .h/.cpp file, I included though.
ozke
@ozke: Y has a complete type if you include the full definition. I can't fix your #includes.
DeadMG
Thanks. I'll keep trying to find where the error is.
ozke
+1  A: 

I think there may be two issues here:

1) You need to declare the ParentClass (i.g. #include its .hpp-file) before using it

2) The assignment "parentInstance = _instance" will invoke the assignment operator, which i'm guessing is not what you want. let "parentInstance" be a pointer instead.

S.C. Madsen
I include the .h file and declare ParentClass (Class ParentClass) but I get this error:h:40: error: field 'parentInstance' has incomplete type
ozke
I think you need to post some code, if you want help with fixing that...
S.C. Madsen
+1  A: 

Note the section on "#include." http://www.cplusplus.com/doc/tutorial/program_structure/

After the "Intro to the C++ Language" section look for the verbiage about #include. http://www.cprogramming.com/tutorial/lesson1.html

Namespaces: http://www.tenouk.com/Module23.html

HTH

JustBoo
A: 

Madsen is on the right track here, but we need more code; What is the class heirarchy of ParentClass, ClassName and SaleraApp. Which classes are base and/or dervied?

When you write: parentInstance = _instance; the compiler will try to generate a default copy constructor if one is not defined. Your problem might be that you are trying to create a dervied class object from a base class pointer.

Also, "this" is a pointer.

Jess
+2  A: 

The problem is you have a circular reference - Game includes MainApp, and MainApp includes game. You need a 'forward declaration', as per the example by DeadMG.

See here.

sje397
Uh, that was EXACTLY the problem I was having. Thanks a lot.Also thanks to the rest. :) Most of the answers were pointing to the right direction. My fault for not posting more code before.
ozke
Problem is... the compiler now can't find the app functions I'm trying to call as it's not strong typed anymore.error: invalid use of incomplete type 'struct MainApp'
ozke
It will remain strongly typed. But note as per that other answer tho, you will need to use a pointer in one of your classes - you can't 'use' a class until it is defined, so two classes can't 'use' each other. But the compiler can deal with a pointer - they're all the same.
sje397
I use Game::Game(MainApp* _app){ app = _app; } but the previous error comes up after calling cout << app->returnSomething() << endl; as if the compiler didn´t know what kind of object app is.
ozke
You need the forward declaration (i.e. `class MainApp;`) before you declare the pointer, but you need the *real* declaration (i.e. `class MainApp {/* ... */};`) before you call any functions using the MainApp pointer. Usually, you have the forward declaration before Game, in Game.h, don't include the MainApp header there, but include the Game.h header in the MainApp.cpp file before you call any MainApp functions.
sje397
I added an update to explain the problem I have when using your method.
ozke
You still need to include MainApp.h at the top of Game.cpp - and don't do anything with the `_app` pointer in Game.h - just in Game.cpp
sje397
But I should declare Game(MainApp* _app); in Game.h right? Since I'm passing app as a constructor parameter.I don't get why this is so hard with C++. It's a piece of cake in other languages. Thanks a lot for your help btw...
ozke
Yes, that's right. Just remember: #include is exactly the same as pasting the included text right there...and you can't call a function before it is defined :)
sje397
A: 

If all you need to do is use functions and data members of another class, read up on the friend keyword. It will allow access to class members from other classes.

UPDATE: Alternatively, store a pointer or reference to the object you need access to, and make getters for data members and make the functions public... but I get the feeling this is not what you're after...

rubenvb
I tend to ignore friend keyboard as I consider it an enemy of encapsulation but, of course, that's a personal choice and friend can still be useful in some scenarios.Thanks for your answer :)
ozke