Accessing an inherited class's variables
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
(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
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.
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 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
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 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.
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
Code:
((cSubClass *)array[i])->subclassThingIf you have to do something like this, you probably have very poor OO design.
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:
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: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()Then you define update for your subclass.
{
// Do stuff
}
Quote:virtual void Child::update()To use the Child's implementation you do this.
{
// Do stuff with child members.
}
Quote:Parent* instance = new Child();Finally if you need to force the use of the Parent implementation you do this.
instance->update(); // Use the child implementation.
Quote:instance->Parent::update(); // Use the parent implementation (I may be wrong on the syntax here...)
Ahh thanks, that's cleared some things up 
What about if I wanted to access a subclasses' variables though? Would I have to make a function to return the variable?
Tobs

What about if I wanted to access a subclasses' variables though? Would I have to make a function to return the variable?
Tobs
Tobs_ Wrote:Ahh thanks, that's cleared some things up
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.

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;
}
That makes things a bit clearer, thanks 
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

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
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.
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.
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.
Hmm, that didn't work even after OneSadCookie had changed the code. I tried using:
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
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;
}"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
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
((Child *)p2)->c
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.
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.
Hi!
I worked on your program a little and took out the errors ^_^
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;
}
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)
Possibly Related Threads...
| Thread: | Author | Replies: | Views: | Last Post | |
| SQLite3 question: accessing by column instead of index? | Toontingy | 3 | 3,247 |
Apr 8, 2010 06:19 PM Last Post: OneSadCookie |
|
| C: Global Variables versus Parameters | Lizard Man | 10 | 4,966 |
Jan 13, 2010 08:22 PM Last Post: Lizard Man |
|
| Noob: Accessing Structures from Cocoa Classes | MikeC | 15 | 6,574 |
Oct 19, 2007 02:42 PM Last Post: MikeC |
|
| Problems with variables in Obj-C | vnvrymdreglage | 16 | 5,920 |
Oct 2, 2006 10:19 PM Last Post: vnvrymdreglage |
|
| Should global variables be pointers or full objects? | ia3n_g | 1 | 2,066 |
Aug 4, 2006 05:53 PM Last Post: OneSadCookie |
|

