Definig a Class within a Class

G

Guenther Sohler

This is probably very easy to answer but for me its new.
Yesterday I realized the need to be able to define a class within another
one. So I have written some test code and its almost syntax error free.

My first goal is to count the Outer classes with a global variable, which
works fine

But then I want to count the Inner classes within the Outer class.
The Varibale innernum is global in repsect to the Class Inner, but
I dont know how to access it.
The error I am getting is
class.cpp: In constructor `Outer::Inner::Inner()':
class.cpp:48: error: type `Outer' is not a base type for type `Outer::Inner'

Its commented in the testcode below. If somebode could show me the right
syntax, I would be happy.
rds


#include <stdio.h>

int outernum=0;

class Outer
{
public:

Outer(void);
~Outer();
void test(void);
int innernum;

class Inner
{
public:

Inner(void);
~Inner();
};
};

Outer::Outer(void)
{
printf("Outer::Outer\n");
innernum=0;
outernum++;
printf("outernum=%d\n",outernum);
}

Outer::~Outer()
{
printf("Outer::~Outer\n");
outernum--;
printf("outernum=%d\n",outernum);
}

void Outer::test(void)
{
printf("Outer::test\n");
Inner a;
Inner b;
}

Outer::Inner::Inner(void)
{
printf("Outer::Inner::Inner\n");
// Outer::innernum++;
// printf("innernum=%d\n",Outer::innernum);
}

Outer::Inner::~Inner()
{
printf("Outer::Inner::~Inner\n");
// Outer::innernum--;
// printf("innernum=%d\n",Outer::innernum);
}

int main(void)
{
Outer a;
Outer b;
a.test();
return 0;
}
 
A

Attila Feher

John Harrison wrote:
[SNIP]
Your code is correct, your compiler is broken. Get a better compiler.

False. Inner classes have no special access to the outer class in C++.

Attila aka WW
 
J

John Harrison

Guenther Sohler said:
This is probably very easy to answer but for me its new.
Yesterday I realized the need to be able to define a class within another
one. So I have written some test code and its almost syntax error free.

My first goal is to count the Outer classes with a global variable, which
works fine

But then I want to count the Inner classes within the Outer class.
The Varibale innernum is global in repsect to the Class Inner, but
I dont know how to access it.
The error I am getting is
class.cpp: In constructor `Outer::Inner::Inner()':
class.cpp:48: error: type `Outer' is not a base type for type `Outer::Inner'

Its commented in the testcode below. If somebode could show me the right
syntax, I would be happy.
rds


#include <stdio.h>

int outernum=0;

class Outer
{
public:

Outer(void);
~Outer();
void test(void);
int innernum;

class Inner
{
public:

Inner(void);
~Inner();
};
};

Outer::Outer(void)
{
printf("Outer::Outer\n");
innernum=0;
outernum++;
printf("outernum=%d\n",outernum);
}

Outer::~Outer()
{
printf("Outer::~Outer\n");
outernum--;
printf("outernum=%d\n",outernum);
}

void Outer::test(void)
{
printf("Outer::test\n");
Inner a;
Inner b;
}

Outer::Inner::Inner(void)
{
printf("Outer::Inner::Inner\n");
// Outer::innernum++;
// printf("innernum=%d\n",Outer::innernum);
}

Outer::Inner::~Inner()
{
printf("Outer::Inner::~Inner\n");
// Outer::innernum--;
// printf("innernum=%d\n",Outer::innernum);
}

int main(void)
{
Outer a;
Outer b;
a.test();
return 0;
}

Your code is correct, your compiler is broken. Get a better compiler.

john
 
I

Immanuel Albrecht

This is probably very easy to answer but for me its new.
Yesterday I realized the need to be able to define a class within
another one. So I have written some test code and its almost syntax
error free.

My first goal is to count the Outer classes with a global variable,
which works fine

But then I want to count the Inner classes within the Outer class.
The Varibale innernum is global in repsect to the Class Inner, but
I dont know how to access it.
The error I am getting is
class.cpp: In constructor `Outer::Inner::Inner()':
class.cpp:48: error: type `Outer' is not a base type for type
`Outer::Inner'


You cannot access any nonstatic member of Outer inside Inner. Because:
your Inner class is inside the namespace of Outer, but that's all. Any
Inner is not bound to any Outer, so there the Outer object carrying the
count variable does not need to be present and is not accessible via
Inner.

If you want to access any Outer nonstatic data members you need an
Outer*this pointer to modify them.

Just keep in mind that the following also is legal:

//your classes snipped.

//at global scope:

Outer::Inner inner_class; //legal, Inner is public in Outer.

I think what you actually were looking for is factory pattern, so that
any Inner has an outbound Outer class.
 
J

John Harrison

Attila Feher said:
John Harrison wrote:
[SNIP]
Your code is correct, your compiler is broken. Get a better compiler.

False. Inner classes have no special access to the outer class in C++.

Attila aka WW

I know, but the OP claimed the code was causing compile errors. I compiled
his code on two different compilers without errors. Are you saying that the
code posted shouldn't compile?

john
 
J

Josephine Schafer

John Harrison said:
Attila Feher said:
John Harrison wrote:
[SNIP]
Your code is correct, your compiler is broken. Get a better compiler.

False. Inner classes have no special access to the outer class in C++.

Attila aka WW

I know, but the OP claimed the code was causing compile errors. I compiled
his code on two different compilers without errors. Are you saying that the
code posted shouldn't compile?
OP said that the offending lines had been commented out.
The code should not compile as inner classes have no special access to outer
classes as pointed by Attila.
 
J

John Harrison

John Harrison said:
Attila Feher said:
John Harrison wrote:
[SNIP]
Your code is correct, your compiler is broken. Get a better compiler.

False. Inner classes have no special access to the outer class in C++.

Attila aka WW

I know, but the OP claimed the code was causing compile errors. I compiled
his code on two different compilers without errors. Are you saying that the
code posted shouldn't compile?

OK my mistake, I didn't realise the OP had commented out the troublesome
lines.

To the OP, its not a good idea to comment out the lines you are having
trouble with. People like me will just cut and paste your code without
realising they have to alter it first.

john
 
A

Attila Feher

Josephine Schafer wrote:
[SNIP]
OP said that the offending lines had been commented out.
The code should not compile as inner classes have no special access
to outer classes as pointed by Attila.

In addition to that (IIRC) you canot even make them friends. I do not
recall if it was making inner the friend of outer or vica versa... But the
point was is that the class has not been defined yet at the point where you
want to make it a friend. So the language is actually going to change to
allow access (friendship) by default. I am so dumb nowadays that I do not
recall exactly what was said in Oxford. :-(
 
N

Nils Petter Vaskinn

In addition to that (IIRC) you canot even make them friends. I do not
recall if it was making inner the friend of outer or vica versa... But the
point was is that the class has not been defined yet

Wouldn't a declaration of the classes first fix that?

regards
NPV
 
I

Ivan Vecerina

| This is probably very easy to answer but for me its new.
| Yesterday I realized the need to be able to define a class within another
| one. So I have written some test code and its almost syntax error free.
|
| My first goal is to count the Outer classes with a global variable, which
| works fine
|
| But then I want to count the Inner classes within the Outer class.
| The Varibale innernum is global in repsect to the Class Inner, but
| I dont know how to access it.

Here's a way to do it:

class Inner {
public:
Inner(Outer& owner) : owner_(owner) { ++owner_.innernum; }
~Inner(Outer& owner) { --owner_.innernum; }

private:
Outer& owner_;
};

Be careful that all 'Inner' instanced attached to an instance of Outer
are destroyed before the 'Outer' instance.
You may want to check this with an assert in Outer::~Outer:
assert( this->innernum == 0 );


hth,
 
G

Guenther Sohler

Thank you for the many answers.

OK. Next time i will not comment it anymore.
I just commented it because I thought it was completely wrong.
It was jsut meant to be a comment for that which should go there.
Outer::Inner inner_class; //legal, Inner is public in Outer.

I think what you actually were looking for is factory pattern, so that
any Inner has an outbound Outer class.
Yes, sounds like that I want.
But I dont want to care for an outer pointer. Cant this link be done
automatically ?
Inner is always called within a Outer class. And so the link information
is given.
Actually this is just a test to test the capabilities of hierarchical
classes.
If my Attempt works, I will extend all that to a bigger database/handle
issue.
The Varibale inenrnum will become a database within System,
and Inner will become a Handle class.
The big advantage of the Inner class in contrast to just a int as
handlenum
is that I can define constructor and destructor code, which is important
for the functionality of the whole system.
So I dont have to do it manually. every time.

Did anybody understand my intention ?

rds
 
I

Immanuel Albrecht

Wouldn't a declaration of the classes first fix that?

Of course that will. A class doesn't need to be defined when making
friends, but known.

namespace test {
class Outer;

class Outer
{
class Inner {

friend class ::test::Outer;

};

friend class Inner;
};

}
 
A

Agent Mulder

GS> If somebode could show me the right
GS> syntax, I would be happy.

Does this what you want?

#include <iostream>
int number=0;
class Outer
{
public:int number;
public:Outer():number(0){++::number;new Inner(this);show();}
public:virtual~Outer(){--::number;show();}
public:void test(){Inner a(this),b(this);show();}
public:void show()
{
std::cout<<"\nNumber of Outers: "<<::number;
std::cout<<"\tNumber of Inners: "<<number;
}
class Inner
{
public:Inner(Outer*a):eek:uter(a){++outer->number;outer->show();}
public:virtual~Inner(){--outer->number;outer->show();}
private:Outer*outer;
};};
int main(int argc,char**argv)
{
Outer a,b,c;
a.test();
return 0;
}
_______
output:
Number of Outers: 1 Number of Inners: 1
Number of Outers: 1 Number of Inners: 1
Number of Outers: 2 Number of Inners: 1
Number of Outers: 2 Number of Inners: 1
Number of Outers: 3 Number of Inners: 1
Number of Outers: 3 Number of Inners: 1
Number of Outers: 3 Number of Inners: 2
Number of Outers: 3 Number of Inners: 3
Number of Outers: 3 Number of Inners: 3
Number of Outers: 3 Number of Inners: 2
Number of Outers: 3 Number of Inners: 1
Number of Outers: 2 Number of Inners: 1
Number of Outers: 1 Number of Inners: 1
Number of Outers: 0 Number of Inners: 1
 
K

Kevin Aylward

Guenther said:
Thank you for the many answers.

OK. Next time i will not comment it anymore.
I just commented it because I thought it was completely wrong.
It was jsut meant to be a comment for that which should go there.

Yes, sounds like that I want.
But I dont want to care for an outer pointer. Cant this link be done
automatically ?
Inner is always called within a Outer class. And so the link
information is given.
Actually this is just a test to test the capabilities of hierarchical
classes.
If my Attempt works, I will extend all that to a bigger
database/handle issue.
The Varibale inenrnum will become a database within System,
and Inner will become a Handle class.
The big advantage of the Inner class in contrast to just a int as
handlenum
is that I can define constructor and destructor code, which is
important for the functionality of the whole system.
So I dont have to do it manually. every time.


You don't need nested classe *definitions* to do this.
Did anybody understand my intention ?

Probably, but why use a nested class definition in the first place? Just
define the inner class as any other normal class on its todd. There is
no reason to be more complicated than need be. The fact that you have
actually posted this question suggests to me that you don't have enough,
with all due respect, knowledge to evaluate why you think this method is
a better way. Unless you can *solidly* back up *why* you want to nest
classes, don't do it. By and large, all a nested class is going to do is
allow you to use that same lexical name for something else!


Kevin Aylward
(e-mail address removed)
http://www.anasoft.co.uk
SuperSpice, a very affordable Mixed-Mode
Windows Simulator with Schematic Capture,
Waveform Display, FFT's and Filter Design.
 
G

Guenther Sohler

Thank you very much for that idea,

but in that case I could simplify the problem by just defining inner and
Outer next to each other, not inside.
This would also work.

Would it ?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,202
Messages
2,571,057
Members
47,665
Latest member
salkete

Latest Threads

Top