Discuss C++: Accessing outer class from inner class? in the C Programming forum on Dev Shed. C++: Accessing outer class from inner class? C programming forum discussing all C derivatives, including C#, C++, Object-C, and even plain old vanilla C. These languages are low level languages, and used on projects such as device drivers, compilers, and even whole computer operating systems.
The ASP Free website provides in-depth information on the latest developer tools available from Microsoft. Our cadre of writers, highly experienced industry experts, reveals the best ways to use established technologies as well as new and emerging technologies. Our coverage of Microsoft's development and administration technologies is among the most respected in the IT industry today.
ASP Free and Iron Speed Designer are giving away $5,500+ in FREE licenses. Iron Speed's RAD CASE toolset can save up to 80% of your coding time. One free license per week, one perpetual license per month! Download and Activate to enter!
Intel® Graphics Performance Analyzers is a powerful tool suite for analyzing and optimizing your games, media, and graphics-intensive applications. Used by some of the best developers on the planet, Intel GPA lets you maximize your app’s performance.
Posts: 110
Time spent in forums: 1 Day 5 h 9 m 27 sec
Reputation Power: 22
C++: Accessing outer class from inner class?
I have an outer class with multiple inner classes. Currently, I'm using a member inside the inner classes to point to the outer class, but I have tons of instances of the outer class and all these internal pointers are taking up too much space.
Is there a way to access the outer class from an inner class without using a member pointer within the inner class? I think I could probably create a function within the outer class that returns 'this', but I'm wondering if there's another way.
I don't care if it's a hack or if it's bad coding practice. I just want those pointers out.
Posts: 920
Time spent in forums: 1 Week 11 h 50 m 18 sec
Reputation Power: 534
Addressing your problem requires redesign, not just a hack to get rid of the pointers.
What you've essentially done is make your outer class into a "god class", as far as your inner classes are concerned. In other words, your inner classes need some information from the outer class in order to function. Needing to pass pointers to your outer class around is a classic symptom of a "god class".
In broad terms, what you need to do is move functionality out of your inner classes, and have it implemented by the outer class, and have a design constraint that requires inner classes to be self-contained, and able to function independently of the outer class.
Without knowing specifics of your class structure, it's difficult to comment further. However, I repeat, that you have a fundamental design problem, and probably need to redesign your complete class structure from scratch.
Posts: 110
Time spent in forums: 1 Day 5 h 9 m 27 sec
Reputation Power: 22
Quote:
Originally Posted by LittleGrin
In other words, your inner classes need some information from the outer class in order to function.
I think you misunderstand the problem. My inner classes don't use any information from the outer class at all. I simply want a pointer to the outer class.
Location: Woodland Hills, Los Angeles County, California, USA
Posts: 8,978
Time spent in forums: 1 Month 2 Weeks 6 Days 22 h 11 m 29 sec
Reputation Power: 3561
I don't think you can eliminate it. One way to do it would be to pass a reference to the outer class to the inner class's constructor. I don't see why the pointers take up so much space. Untested code:
Code:
class outer {
private:
int x;
class inner {
private:
outer *out;
inner(outer *o) { out = o; }
int do_something(void) {
out->x = 10;
return out->x;
}
};
};
__________________ Up the Irons
What Would Jimi Do? Smash amps. Burn guitar. Take the groupies home. "Death Before Dishonour, my Friends!!" - Bruce D ickinson, Iron Maiden Aug 20, 2005 @ OzzFest
Down with Sharon Osbourne Diary of a first time dog owner <-- my cousin's blog
Posts: 110
Time spent in forums: 1 Day 5 h 9 m 27 sec
Reputation Power: 22
That's what I have now, but I don't access the insides of 'out'. What I'm trying to do is eliminate "outer *out" and instead be able to call a function or somehow compute 'out'.
Posts: 110
Time spent in forums: 1 Day 5 h 9 m 27 sec
Reputation Power: 22
Found it.
Code:
class outer {
private:
int x;
class inner {
private:
int do_something(void) {
outer *ptr = (outer*)((size_t)this - (size_t) &(((outer*)0)->in));
// call some func with ptr.
}
} in;
};
Posts: 4,405
Time spent in forums: 4 Weeks 1 Day 9 h 41 m 54 sec
Reputation Power: 1719
Quote:
Originally Posted by Vorlath
I think you misunderstand the problem. My inner classes don't use any information from the outer class at all. I simply want a pointer to the outer class.
If it needs nothing from the outer class, then you don't need the pointer! I think it is you that has misunderstood. Your inner class requires services from the outer class (and thus albeit indirectly, acesses information from the outer class) - that is what LittleGrin meant, and he is correct that your design is suspect.
Your solution is nasty BTW, I am not even going to begin to try to fathom whether it will work in all circumstances (i.e. whether it is guaranteed to work by the ISO standard).
If the outer class is a singleton object, then using the singleton pattern is the correct solution, any class whether internal or external can access it then.
Your "create a function within the outer class that returns 'this'" is in fact only viable for a singleton pattern. For a normal object you if you could do that you would not need to!
Unless you are writing code for a resource constrained embedded system, you assertion that the pointers take up too much space is almost certainly wrong. How much is too much space, and why?
If by 'space' you simply mean source code length by having to add this member to all your classes, then the solution to that is simple; make all your inner classes subclasses of a class containing the pointer. Of course there may be little advantage in this since you then need a constructor.
Code:
class outer
{
public:
void func() ;
private :
class hasParent
{
public :
hasParent( outer* p ) : parent(p) {}
outer* parent ;
} ;
class inner
{
inner() : hasParent( this ){}
int do_something(void)
{
parent->func() ;
}
} ;
} ;
Posts: 110
Time spent in forums: 1 Day 5 h 9 m 27 sec
Reputation Power: 22
clifford,
I'm never worried about source code size. I'm worried about runtime size. If I have a data structure that is 128 bytes each, then removing 16 of those bytes will make a huge impact space-wise. At 128 bytes each, that's about 8.3 million entries in 1GB of memory. At 112 bytes each, I can get 9.5 million entries. A 15% increase. So that these pointers are taking too much space is exactly right. It's even more drastic for smaller initial structure sizes.
About needing information from the outer class, you may have heard of templates??? Like vector or list that can store pointer types? They do not need information from the item they are storing. It only needs the pointer. So again, your assumption is wrong.
And about my solution being nasty, it's not that bad. It's one line. I've documented it and I only need it to work in ONE compiler. And it does. I wish it was cleaner, but I knew going in it was likely to be a hack and said as much.
I appreciate your willingness to help. I've enjoyed your comments and suggestion in the past. I only ask that the easily avoidable false assumptions be kept to a minimum.
Posts: 1,713
Time spent in forums: 1 Month 2 Weeks 1 Day 33 m 13 sec
Reputation Power: 1495
I think we will need to see the actual code, or at least for you to tell us something about what you're trying to do with the outer-class pointer. We can't really judge the construct itself without knowing what it is meant for, nor give meaningful suggestions about it.
Is the inner class used only for a single instance variable of the outer class? Your example code seems to imply this, with the in declaration at the end of the class definition, though you did give the class a name as well (if you only need a single variable of that class, IIUC you can leave the class itself anonymous, just as you can with structs).
FOR SALE: One ShapeSystem 2300 CMD, extensively modified for human use. Includes s/w for anthro, transgender, sex-appeal enhance, & Gillian Anderson and Jason D. Poit clone forms. Some wear. $4500 obo. tverres@et.ins.gov
Last edited by Schol-R-LEA : January 15th, 2009 at 05:17 AM.
Reason: grammar fix.
Posts: 920
Time spent in forums: 1 Week 11 h 50 m 18 sec
Reputation Power: 534
Quote:
Originally Posted by Vorlath
I think you misunderstand the problem. My inner classes don't use any information from the outer class at all. I simply want a pointer to the outer class.
Well, no, by this comment you've convinced me that I understood the problem. Your design is broken, but you are assuming your design is correct, and seeking a hack to make things work anyway.
If the inner class doesn't use information from the outer class, it wouldn't have any need for the pointer.
Quote:
Originally Posted by Vorlath
Found it.
Code:
class outer {
private:
int x;
class inner {
private:
int do_something(void) {
outer *ptr = (outer*)((size_t)this - (size_t) &(((outer*)0)->in));
// call some func with ptr.
}
} in;
};
The fact you are trying to call some function with ptr in this means your inner class is reliant on the outer class.
There is also the inconvenient fact that this fix you have "found" exhibits undefined behaviour. Firstly it relies on particular relationships in terms of how inner classes and outer classes are laid out in memory. Second it dereferences a NULL pointer.
Posts: 110
Time spent in forums: 1 Day 5 h 9 m 27 sec
Reputation Power: 22
My design is just fine. I'll describe what I'm doing for the curious.
I used to have an inner function that took a parameter, but I needed to enforce a rule where the outer instance was always the same as where the inner one is found. So I decided to pass 'this' to the inner class' constructors. This worked just fine and there has never been any problems other than the recent issue with memory usage.
I allocate millions of these structures, so I wanted to reduce the footprint. I've found a hack to get rid of the internal pointers. I only need it to work on ONE compiler. So to those that say it has undefined behaviour, who cares? It works. This hack is not to make the design work. It already works just fine without the hack. I just require a smaller memory footprint and this hack allows for that.
And yes, there is only ONE inner instance of each inner class per outer class and is never used elsewhere. I use it for scoping since the inner classes have similar function names, but are used for different, yet similar, purposes. It's basically used to allow forward and backlinks between nodes (the outer class). This is why I don't need information about the outer class any more than vector<outer*> does. The vector has no knowledge of the outer class. All it knows about is the pointer. That's all I care about too.
It's a rather simple concept. I can't really screw it up since it's so simple. I just wanted to reduce useless memory usage. Just because I use a hack to do this doesn't mean my design is flawed.
Location: Woodland Hills, Los Angeles County, California, USA
Posts: 8,978
Time spent in forums: 1 Month 2 Weeks 6 Days 22 h 11 m 29 sec
Reputation Power: 3561
I think you should document your pointer magic very well for a future maintainer along with compiler version and optimization settings used to make this work.
without getting a SEGFAULT? Unless you get a special hardware where 0x0 is actually an address readable by a user program?
I guess you try to imagine how the class is to be built in memory by your compiler.
Something like?
Code:
this - sizeof(int) - sizeof(outer *)
Even sticking with a particular compiler and settings (try with both debug and optimized code), nothing guarantees you how the class will be ordered (members, etc.)
I'd be happy to hear some kind of proof that it works.
PS: the fact that the program actually runs fine with a particular set of data can't be considered a proof, can it?
__________________
etienne:~ > %blow
fg: %blow: no such job
There are 10 kind of people:
- those who know binary
- those who don't.
Posts: 4,405
Time spent in forums: 4 Weeks 1 Day 9 h 41 m 54 sec
Reputation Power: 1719
Quote:
Originally Posted by Vorlath
About needing information from the outer class, you may have heard of templates??? Like vector or list that can store pointer types? They do not need information from the item they are storing. It only needs the pointer. So again, your assumption is wrong.
I will admit that I have no idea what your point is there.
I think you persist in misunderstanding the original point which was a simple one. You said that the inner requires nothing of the outer class, yet showed an example of it calling a member function of the parent. That was the point made, there was a contradiction in your statements that is all, A simple clarification was all that was required, not an argument.
With respect to your example above I think you are referring to STL container classes (rather than templates per se - while STL containers are template classes, template classes are not exclusively STL containers), but these are not an example of what you have described in any case, the contained objects are entirely unaware of the containing object, and the container class itself too knows nothing about the contained objects.
Posts: 920
Time spent in forums: 1 Week 11 h 50 m 18 sec
Reputation Power: 534
Quote:
Originally Posted by Vorlath
It's a rather simple concept. I can't really screw it up since it's so simple. I just wanted to reduce useless memory usage. Just because I use a hack to do this doesn't mean my design is flawed.
The fact that you needed to use a hack is evidence your design is flawed. Your ability to delude yourself otherwise does not alter the evidence.