468,503 Members | 2,039 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,503 developers. It's quick & easy.

inner class accessing outer

Hi folks,

I've got something like:

class Outer {
int f();

friend class Inner;
class Inner {
int g() {
// call f from here
}
}
}
and I want to call Outer::f from inside g. Simply doing Outer::f()
doesn't work, gcc complains it doesn't have an object pointer (which is
somehow bogus, imho -- the compiler could derive a pointer to Outer
because Inner is instantiated within Outer).

Or could I perhaps obtain Outer's this from Inner?

I'm aware of the workaround that involves passing a pointer to the Outer
instance to Inner's constructor. That's what I'd like to avoid.

Thanks.
Nov 26 '07 #1
9 4230
Matthias Buelow wrote:
I've got something like:

class Outer {
int f();

friend class Inner;
I am not sure this is necessary...
class Inner {
int g() {
// call f from here
}
}
}
I believe a few semicolons are missing here...
and I want to call Outer::f from inside g.
On what 'Outer' object? Do you have an 'Outer' object to call 'f'
for? 'f' is non-static, so you need an object of class 'Outer' which
to supply to 'f' as the hidden argument.
Simply doing Outer::f()
doesn't work, gcc complains it doesn't have an object pointer
Correct.
(which
is somehow bogus, imho -- the compiler could derive a pointer to Outer
because Inner is instantiated within Outer).
Who is instantiated inside of whom? 'Inner' _class_ is *declared*
insde the 'Outer' _class_. There is no relationship between them
from the instances POV. C++ is not Java.
Or could I perhaps obtain Outer's this from Inner?
If your 'Inner' keeps a {pointer to|reference to|instance of} Outer,
you can of course "obtain" it from 'this'. Otherwise, you need to
pass the 'Outer' you need as the argument.
I'm aware of the workaround that involves passing a pointer to the
Outer instance to Inner's constructor. That's what I'd like to avoid.
Don't pass it to the constructor. Pass it to 'g'.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Nov 26 '07 #2
Victor Bazarov wrote:
I believe a few semicolons are missing here...
Yes...
Who is instantiated inside of whom? 'Inner' _class_ is *declared*
insde the 'Outer' _class_. There is no relationship between them
from the instances POV. C++ is not Java.
Errm. I posted a bit carelessly. Suppose that:

class Outer {
int f() {}
class Inner {
int g() { /* want to call f here */ }
} inner;
};

Now Outer::Inner::g() could possibly have access to the Outer object, if
the compiler does the Right Thing... but apparently it's not supported
or is it somehow, that's what I want to know.
Nov 26 '07 #3
Victor Bazarov wrote:
but if 'inner' is the only member in 'Outer', it
Yeah, except that it isn't, in my real code.
class SomeOtherOuter {
double a;
char *b;
Outer::Inner myowninner;
};

and call 'g' for 'myowninner'? Yeah, yeah, you can claim that 'Inner'
is private in 'Outer' (what if it isn't?) but I can then say that I
edit the 'Outer' to make 'SomeOtherOuter' a friend... See how easy it
is to bring down that house of cards?
Hmm.. this is indeed a counter-example. However, if an inner class
hypothetically accessed parts of its outer class "directly", the
compiler could flag an error if the inner class would be used anywhere
outside of the outer class it is defined in (or automatically make it
"private" or somesuch).
The only reliable way is to let 'Inner' instance know in what 'Outer'
it is contained. And you already know how to do that. Another way
is _not_ to let 'Inner' know, but pass 'Outer' as the argument to
the 'g()'.
Yeah.. but it's more typing (and hence uglier code..)
Nov 26 '07 #4
Victor Bazarov wrote:
There is no "its outer class". I am guessing you don't get the point
that 'Inner's being declared inside 'Outer' is inconsequential to the
nature of 'Inner'-'Outer' relationship as far as C++ is concerned.
That's not entirely true -- consider the following example:

class Outer {
typedef int T;
public:
class Inner {
T x;
};
};

this could be extended to object relationship (not just types).
That's nonsense. It would limit the use of 'Inner' to inside of the
"outer" class, which is unacceptable;
In this case it would be the behaviour I want; certainly far from
"nonsense".
And 'Inner' cannot know whether
it's declared "private" or not inside the 'Outer'. Heck, 'Inner'
has really no idea that it's declared inside some other scope at
all (not that it's disallowed to gain access to that information,
it just doesn't have any need in most cases).
"Inner" doesn't; but the compiler does.
Nov 26 '07 #5
On Mon, 26 Nov 2007 14:55:56 +0100, Matthias Buelow wrote:
Hi folks,

I've got something like:

class Outer {
int f();

friend class Inner;
class Inner {
int g() {
// call f from here
}
}
}
and I want to call Outer::f from inside g. Simply doing Outer::f()
doesn't work, gcc complains it doesn't have an object pointer (which is
somehow bogus, imho -- the compiler could derive a pointer to Outer
because Inner is instantiated within Outer).

Or could I perhaps obtain Outer's this from Inner?

I'm aware of the workaround that involves passing a pointer to the Outer
instance to Inner's constructor. That's what I'd like to avoid.

Thanks.
First of all - you mistake C++ and Java. C++ inner classes are like
static inner classes in Java - no owning object of outer class, so no
pointer to it. You have to give an Outer object to g somehow (a parameter
to g or a parameter to Inner constructor).
Second:
friend class Inner;
is a way to let functions of class Inner access private members of class
Outer (good idea as f seems to be private). But you must put this line
after definition of class Inner. Otherwise the compiler will assume you
are referring to a class defined somewhere outside the class Outer not
the class you intended.

HTH
--
Tadeusz B. Kopec (tk****@NOSPAMPLEASElife.pl)
Ahead warp factor one, Mr. Sulu.
Nov 26 '07 #6
Matthias Buelow wrote:
Victor Bazarov wrote:
>There is no "its outer class". I am guessing you don't get the point
that 'Inner's being declared inside 'Outer' is inconsequential to the
nature of 'Inner'-'Outer' relationship as far as C++ is concerned.

That's not entirely true -- consider the following example:

class Outer {
typedef int T;
public:
class Inner {
T x;
};
};

this could be extended to object relationship (not just types).
I wonder how. Instances don't have scopes. Members don't exist
without instances. Here, you have 'T' which is a name that can be
looked up at the compilation time, and the scope of 'Outer::Inner'
has a very specific set of rules for name lookup.

Now, remove they 'typedef' (to make 'T' an instance). What do you
have?

class Outer {
int T;
public:
class Inner {
void foo() { T = 42; }
};
};

You have 'T' that is an instance of 'int', but it doesn't exist
in a vacuum. It only exists in an instance of 'Outer'. The
compiler has no idea where that instance of 'Outer' is. No clue
whatsoever. What do you propose? Let's rehearse the conversation
you're going to have in 'comp.std.c++' (see my suggestion below).

You're saying that if you declare an instance of 'inner' inside
an instance of 'Outer', the compiler has to know how to get the
address of one and convert it to the address of the other. How?
What if it doesn't exist?

class Outer {
int T;

class Inner {
void foo() { T = 42; }
} inner;

void bar();
};

void Outer::bar() {
Inner i;
i.foo(); // now what?! Whose 'T' are we changing now?
}

Are you going to prohibit the use of 'Inner' like that? Fine,
somehow 'Inner' is private (as I made it in my last example), but
it should also become incomplete class (so you cannot instantiate
it as a stand-alone object even inside 'Outer' scope)? Then how
do we instantiate the 'Outer::inner' member? See the conflict?
Or do we simply allow 'i' inside 'Outer::bar' to change 'this->T'
somehow?

Think about all possible variations of the use of 'Inner' and not
just how _you_ want to use it. I believe the expression is "to
see beyond one's nose".
>That's nonsense. It would limit the use of 'Inner' to inside of the
"outer" class, which is unacceptable;

In this case it would be the behaviour I want; certainly far from
"nonsense".
But you seem to want to have this behaviour as the norm. It's not
because it cannot be. It just wouldn't make sense as the norm.

It's impossible to make everybody happy, that's true. That's why
the langauges are usually designed to make the majority of people
happy and if a few unhappy people remain, they usually get to use
the work-arounds.
>And 'Inner' cannot know whether
it's declared "private" or not inside the 'Outer'. Heck, 'Inner'
has really no idea that it's declared inside some other scope at
all (not that it's disallowed to gain access to that information,
it just doesn't have any need in most cases).

"Inner" doesn't; but the compiler does.
So? The compiler knows many other things. Every compiler knows
its own set of things, AAMOF. If you need to be able to know the
things the compiler knows, turn to the compiler's manual. If you
want to make what compiler knows available to the programmer and
specify that in the Standard, then it's a different story.

I believe you're arguing a change in the language. I don't think
this is the right newsgroup for it. Try 'comp.std.c++'. Explain
what you think is missing from the language, make a proposal. Do
not forget to have a business case (what problem it solves that
cannot be solved otherwise). Then present your argument and have
the language changed. Or have your mind changed for the work-
around that you're "trying to avoid". Either way, 'comp.std.c++'
is _the_ newsgroup for trying to get your point across to the
people who are on the bleeding edge of making C++ work better.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Nov 26 '07 #7
Victor Bazarov wrote:
I wonder how. Instances don't have scopes. Members don't exist
without instances. Here, you have 'T' which is a name that can be
Well.. one could use lexical scope. This would break the homology with
C, where struct X { struct Y {...}; }; makes struct Y visible within the
whole compilation unit but well.
class Outer {
int T;

class Inner {
void foo() { T = 42; }
} inner;

void bar();
};

void Outer::bar() {
Inner i;
i.foo(); // now what?! Whose 'T' are we changing now?
}
Or do we simply allow 'i' inside 'Outer::bar' to change 'this->T'
somehow?
Well, I see the problem. Changing it to mean "this->T" in this case
would be the most obvious solution, imho. Actually, I think that would
be quite neat but perhaps not fit entirely into the C++ mindframe...
Think about all possible variations of the use of 'Inner' and not
just how _you_ want to use it. I believe the expression is "to
see beyond one's nose".
This could be made even more powerful, like treating T (in this example)
somewhat akin to a free variable and binding it to the (lexically)
surrounding binding, for example:

void Outer::bar() {
int T;
Inner i;
i.foo(); // would refer to T in bar()'s scope
}

This could be resolved at compile-time.

Of course, the next problem would be:

void Outer::bar() {
int T;
Inner *i = new Inner;
i->foo(); // now what?
}

I don't think it's a real show-stopper but I'm not into going into this
now.
I believe you're arguing a change in the language. I don't think
this is the right newsgroup for it. Try 'comp.std.c++'. Explain
I don't really want to; I just didn't know if there wasn't perhaps some
way to have an "inner" class access members of a surrounding class.
Nov 26 '07 #8
On Nov 26, 3:58 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
Matthias Buelow wrote:
I've got something like:
class Outer {
int f();
friend class Inner;
I am not sure this is necessary...
It depends on the version of the standard his compiler
implements. It's probably a good idea, but it almost definitly
should go *after* the definition (or at least a declaration) of
Inner; if it's before, as here, it says that there is some class
named Inner in the enclosing namespace which is a friend.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 27 '07 #9
Matthias Buelow wrote:
Hi folks,

I've got something like:

class Outer {
int f();

friend class Inner;
class Inner {
int g() {
// call f from here
}
}
}
and I want to call Outer::f from inside g. Simply doing Outer::f()
doesn't work, gcc complains it doesn't have an object pointer (which is
somehow bogus, imho -- the compiler could derive a pointer to Outer
because Inner is instantiated within Outer).

Or could I perhaps obtain Outer's this from Inner?

I'm aware of the workaround that involves passing a pointer to the Outer
instance to Inner's constructor. That's what I'd like to avoid.
According to the current standard, it's necessary to declaration nested
class friend.
IIRC, VC does NOT need the friend declaration.

Anyway, your way of declaring nested class a friend is wrong.

class Outter
{
class Inner
{
};
friend class Inner;
};

or

class Outter
{
class Inner; // needed, or else,
friend class Inner; // Inner is a friend from the enclosing namespace

class Inner
{
};
};
Nov 27 '07 #10

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

2 posts views Thread by Murat Tasan | last post: by
3 posts views Thread by trialproduct2004 | last post: by
4 posts views Thread by amaca | last post: by
1 post views Thread by bob | last post: by
5 posts views Thread by Martijn Mulder | last post: by
1 post views Thread by mrstephengross | last post: by
3 posts views Thread by gieforce | last post: by
reply views Thread by fmendoza | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.