iDevGames Forums
Accessing an inherited class's variables - Printable Version

+- iDevGames Forums (http://www.idevgames.com/forums)
+-- Forum: Development Zone (/forum-3.html)
+--- Forum: Game Programming Fundamentals (/forum-7.html)
+--- Thread: Accessing an inherited class's variables (/thread-3469.html)

Pages: 1 2


Accessing an inherited class's variables - Tobs_ - Feb 23, 2007 10:53 AM

The title's probably a little misleading, but I didn't know what else to call it.
(Using C++ in xCode)

In my object management system, I have the parent class 'cParentClass', and object classes e.g. 'cEnemy'. This means I can store them all in a nice big array, and not have to worry about executing cycle events (performed every frame) for each individual object class. My problem comes when, in class 'cEnemy', I try to access the x variable in cPlayer, because of the error:
"error: 'class cParentClass' has no member named 'x'"
In the line:
"targetX = omsList[iPlayer]->x;"
Where 'omsList[iPlayer]' is the instance of cParentClass.
Makes sense, it doesn't have the member, but if I give it the variable, it's there in all my other classes as well, taking up memory isn't it? So is there a better way, or am I trying to access it in the wrong way?

Tobs


Accessing an inherited class's variables - akb825 - Feb 23, 2007 11:34 AM

So are the parent class's private variables actually declared private? If so, there's your problem: private variables mean that absolutely nothing but that class can access those variables, including subclasses. Protected variables, however, are accessible by that class and subclasses, but not from other dependancy trees or globally.


Accessing an inherited class's variables - Tobs_ - Feb 23, 2007 11:50 AM

Everything in all my classes is public, so any subclass should be able to get a variable from any other subclass shouldn't it?

I think the compiler thinks that I want to access the variables of the parent class, not the child, which is fair enough, because omsList is of type 'cParentClass' (with children stored in it), but I can get to the cycle function (defined as a virtual void in the parent class), so is there a way to get to the child's variables?

Tobs


Accessing an inherited class's variables - akb825 - Feb 23, 2007 12:17 PM

Tobs_ Wrote:Everything in all my classes is public, so any subclass should be able to get a variable from any other subclass shouldn't it?

I think the compiler thinks that I want to access the variables of the parent class, not the child, which is fair enough, because omsList is of type 'cParentClass' (with children stored in it), but I can get to the cycle function (defined as a virtual void in the parent class), so is there a way to get to the child's variables?

Tobs
I see, you're trying to access a child class's variables from the parent class. In that case, your only option is to typecast to the child class. Even for virtual functions, they must be declared in the parent class if the object is of the parent class's type. (even if it's only polymorphically in that type) If you want to have some extra security making sure you don't typecast to the wrong type, you can use dynamic_cast<>(), which returns NULL if you cast to an unsupported type. (such as from a different inheritance tree) You can also have an integer with an enumerated value to store information about the type so you know exactly what type it is.


Accessing an inherited class's variables - OneSadCookie - Feb 23, 2007 12:18 PM

Code:
((cSubClass *)array[i])->subclassThing

If you have to do something like this, you probably have very poor OO design.


Accessing an inherited class's variables - Blacktiger - Feb 23, 2007 08:08 PM

I think what he is trying to do is declare a bunch of classes with a member function like update() but where each subclass uses its own implementation that accesses member variables only declared in the subclass. Like so:
Quote:class Parent:
virtual void update();
end Parent;

class Child:
member x;
void update: x++; end update;
end Child;

Parent instances[] = [ childA, childB, etc ];
for instance in instances:
instance->update();
end for;

It's been awhile since I did a major project in c++ and I don't remember how you make sure that the member function called is from the subclass and not the superclass.

Edit:
What you want to do is declare the member function as virtual in the parent.
Quote:virtual void Parent::update()
{
// Do stuff
}
Then you define update for your subclass.
Quote:virtual void Child::update()
{
// Do stuff with child members.
}
To use the Child's implementation you do this.
Quote:Parent* instance = new Child();
instance->update(); // Use the child implementation.
Finally if you need to force the use of the Parent implementation you do this.
Quote:instance->Parent::update(); // Use the parent implementation (I may be wrong on the syntax here...)



Accessing an inherited class's variables - Tobs_ - Feb 24, 2007 03:16 AM

Ahh thanks, that's cleared some things up Smile

What about if I wanted to access a subclasses' variables though? Would I have to make a function to return the variable?

Tobs


Accessing an inherited class's variables - Blacktiger - Feb 26, 2007 08:16 AM

Tobs_ Wrote:Ahh thanks, that's cleared some things up Smile

What about if I wanted to access a subclasses' variables though? Would I have to make a function to return the variable?

Tobs

Ok, well let me give you an actually compilable example. Wink

Code:
#include <iostream>
using namespace std;

class Parent
{
public:
    Parent() { p = 1; }
    virtual void foo() { cout << "Parent " << p << endl; }
protected:
    int p;
};

class Child: public Parent
{
public:
    Child() { p = c = 2; }
    void foo() { cout << "Child " << c << endl; }
protected:
    int c;
};

int main (int argc, char * const argv[])
{
    Parent* p1 = new Parent();
    Parent* p2 = new Child();
    p1->foo(); // Output: Parent 1
    p2->foo(); // Output: Child 2
    p2->Parent::foo(); // Output: Parent 2
    return 0;
}



Accessing an inherited class's variables - Tobs_ - Feb 26, 2007 11:25 AM

That makes things a bit clearer, thanks Smile

2 Final Questions:
Can I access a subclasses' variables? I tried doing
cout << p2->Child::c;
but it didn't like that. Is it possible? Or do I use a function to return the variable?
Do I have do delete all the variables in the class myself in the destructor?

Tobs


Accessing an inherited class's variables - Blacktiger - Feb 26, 2007 05:07 PM

When you declare a variable of type Parent, you are telling c++ that that variable responds to the 'interface' for the Parent. That means that using that variable you can only access members that are public to Parent, not to any Child classes.

If you know what kind of Child class you have, you can use typecasting to access the Child's variables.

Code:
Parent* p2 = new Child();
(Child*)p2->c;

Note that you must know what subclass you are using... so if ChildA has a variable a and ChildB has a variable b and you try to cast the ChildB to a ChildA you get very bad things happening... your program will probably crash when you try to access a or b from the wrong object.


When you create a variable with new, you create new storage on the 'heap'. When you delete a variable, you free the memory in the heap. Only delete variables you created with the new keyword.

When objects are deleted, their destructor is called. The destructor should be used to delete and remaining member variables that you haven't already deleted.


Accessing an inherited class's variables - Tobs_ - Feb 27, 2007 08:30 AM

Hmm, that didn't work even after OneSadCookie had changed the code. I tried using:
Code:
#include <iostream>
using namespace std;

class Parent
{
public:
    Parent() { p = 1; }
protected:
    int p;
};

class Child: public Parent
{
public:
    Child() { p = c = 2; }
    int c;
};

int main (int argc, char * const argv[])
{
    Parent* p2 = new Child();
    cout << (Child*)p2->c;
    return 0;
}
But it just tells me
"error: 'class Parent' has no member named 'c'"
Which makes sense because it doesn't, but shouldn't it try and get the Child's 'c' variable instead?

Tobs


Accessing an inherited class's variables - akb825 - Feb 27, 2007 01:17 PM

Check the order of operations. It does the -> first, which means it's trying to access c from p2 before the typecast. You will need to enclose the cast of p2 in parenthesis like so:
((Child *)p2)->c


Accessing an inherited class's variables - OneSadCookie - Feb 27, 2007 02:15 PM

Whoops, didn't notice that the parentheses were wrong too...

Bottom line is, as I said earlier, you should not be doing this. It violates every principle of OO design. If you think you need to, you should design your class hierarchy in another way.


Accessing an inherited class's variables - mac_girl - Feb 27, 2007 11:55 PM

Hi!
I worked on your program a little and took out the errors ^_^

Code:
#include <iostream>
using namespace std;

class Parent
{
public:
    Parent() { p = 1; }
    void SetP(int x) { p = x; }
    int GetP() const { return p; }
protected:
    int p;
};

class Child: public Parent
{
public:
    Child() : c(2) { SetP(c); }
    int c;
};

int main (int argc, char * argv[])
{
    Child* p2 = new Child();
    
    // show what they were
    cout << p2->c << endl;
    cout << p2->GetP() << endl;

    // then they change
    p2->c = 5;
    p2->SetP(15);
    
    // and now they are
    cout << p2->c << endl;
    cout << p2->GetP() << endl;
    
    delete p2;
    return 0;
}



Accessing an inherited class's variables - akb825 - Feb 28, 2007 12:03 AM

You missed the whole point. The point was to have the Child exist as a Parent, but then access the fields of the child when it's existing as a parent. (hence the typecasting)