By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,572 Members | 963 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,572 IT Pros & Developers. It's quick & easy.

Cannot compile simple example

P: n/a
Mtk
Hi!
Why does the following, simple, example produce such errors?
I know it has to do with the two header files including each other and
(moreover) the usage of the classes One and Two in the "opposite" header
file... What do I have to do to make this example work?

Thanks for all the help!

// * Error messages:
One.h(11): error C2146: syntax error : missing ';' before identifier 't'
One.h(11): error C2501: 'One::Two' : missing storage-class or type
specifiers
One.h(11): error C2501: 'One::t' : missing storage-class or type specifiers
Two.h(11): error C2146: syntax error : missing ';' before identifier 't'
// * File One.h
#ifndef ONE_H
#define ONE_H

#include "Two.h"

class One
{
public:
One();
private:
Two t;
};

#endif

// * File One.cpp
#include "One.h"

One::One()
{
}

// * File Two.h
#ifndef TWO_H
#define TWO_H

#include "One.h"

class Two
{
public:
Two();
private:
One t;
};

#endif

// * File Two.cpp
#include "Two.h"

Two::Two()
{
}

// * File Main.cpp
int main()
{
return 0;
}
Oct 10 '05 #1
Share this Question
Share on Google+
13 Replies


P: n/a
I'm new to this, too. So bear with me.

But your header files are CIRCULAR.

one defines the other. Walk through line by line and there is great
confusion.

You must straighten out the sequence of instructions so there is NO
ambiguity. Then it looks like it should compile ok.

- Robert -

Oct 10 '05 #2

P: n/a
"Mtk" <sp***********@nra.org> wrote in message
news:di**********@news.island.liu.se...
Why does the following, simple, example produce such errors?
I know it has to do with the two header files including each other
Because of the "include guards," the two files only look like including each
other. In effect, one of them includes the other one; and that's it. (Second
one includes the first one too, but at that time the body of the first
header is included as nothing.)
and (moreover) the usage of the classes One and Two in the "opposite"
header file... What do I have to do to make this example work?
You have to use a forward declaration and must use one of the classes as
reference (meaning both reference and pointer) in the other header.
// * Error messages:
One.h(11): error C2146: syntax error : missing ';' before identifier 't'
One.h(11): error C2501: 'One::Two' : missing storage-class or type
specifiers
One.h(11): error C2501: 'One::t' : missing storage-class or type
specifiers
Two.h(11): error C2146: syntax error : missing ';' before identifier 't'
// * File One.h
#ifndef ONE_H
#define ONE_H

#include "Two.h"

class One
{
public:
One();
private:
Two t;
That line is good; because we know what Two is.
};

#endif

// * File One.cpp
#include "One.h"

One::One()
{
}

// * File Two.h
#ifndef TWO_H
#define TWO_H

#include "One.h"
The line above is ineffective, because the macro ONE_H is defined at this
point, so what we include with the line above is "nothing."
class Two
{
public:
Two();
private:
One t;
You have a conceptual problem on the line above. It is not possible to have
two objects include each other; that would be infinite recursively.

At least one of your classes must "refer" to the other one; it should not
include it as a part.
};

#endif


Without knowing your exact requirements, here is one solution:

Don't include "One.h" in Two.h; instead, forward declare One. Then, keep a
reference to a One object in Two, don't contain one:

// * File Two.h
#ifndef TWO_H
#define TWO_H

class One; // <-- Forward declaration

class Two
{
public:
explicit Two(One & one) // <-- Take a reference
:
t(one) // <-- Remember your One
{}

private:
One & t; // <-- Keep a reference

};

#endif

By the way, I think this must be an FAQ.

Ali

Oct 10 '05 #3

P: n/a
Mtk wrote:
Why does the following, simple, example produce such errors?
I know it has to do with the two header files including each other and
(moreover) the usage of the classes One and Two in the "opposite" header
file... What do I have to do to make this example work?
You can't.

Let's condense your example to one file. And let's suppose the compiler
knows about classes 'One' and 'Two' somehow _apriori_.
[...]
class One
{
public:
One();
private:
Two t;
};
[...]
class Two
{
public:
Two();
private:
One t;
};


Now, what is the size of a class One object? As soon as you can come up
with a formula the compiler can use to calculate it, let us know.

Meanwhile, look up "forward declaration".

V
Oct 10 '05 #4

P: n/a
Mtk
Thanks for the reply.

I may be a newbie when it comes to c++, but there must be a simpler
solution to my problem than the one you described.

Not including "One.h" in "Two.h", and attempting to forward-declare
class One, gives the error message "Two.h(10): error C2079: 'Two::t'
uses undefined class 'One'" - of course.

Anyway. I'll take a look at forward declarations.

Thanks again

Ali Çehreli wrote:
[huge snip]
Without knowing your exact requirements, here is one solution:

Don't include "One.h" in Two.h; instead, forward declare One. Then, keep
a reference to a One object in Two, don't contain one:

// * File Two.h
#ifndef TWO_H
#define TWO_H

class One; // <-- Forward declaration

class Two
{
public:
explicit Two(One & one) // <-- Take a reference
:
t(one) // <-- Remember your One
{}

private:
One & t; // <-- Keep a reference

};

#endif

By the way, I think this must be an FAQ.

Ali

Oct 10 '05 #5

P: n/a
Mtk
Hi!

I forgot to mention that I'm a newbie and I have no intention to make
the compiler calculate the size of any class at all (at least for now)
and, thus, I'll skip that part.

I just want class One to have a variable of the "class Two"-type and
vice-versa, giving the requirement that each class is located in its own
header file.

I'll look "forward declarations" up.

Thanks

Victor Bazarov wrote:
Mtk wrote:
Why does the following, simple, example produce such errors?
I know it has to do with the two header files including each other and
(moreover) the usage of the classes One and Two in the "opposite"
header file... What do I have to do to make this example work?


You can't.

Let's condense your example to one file. And let's suppose the compiler
knows about classes 'One' and 'Two' somehow _apriori_.
> [...]
class One
{
public:
One();
private:
Two t;
};
> [...]
class Two
{
public:
Two();
private:
One t;
};


Now, what is the size of a class One object? As soon as you can come up
with a formula the compiler can use to calculate it, let us know.

Meanwhile, look up "forward declaration".

V

Oct 10 '05 #6

P: n/a
"Mtk" <sp***********@nra.org> wrote in message
news:di**********@news.island.liu.se...
Thanks for the reply.

I may be a newbie when it comes to c++, but there must be a simpler
solution to my problem than the one you described.
There isn't a simpler solution. We must break the circular dependency
somehow.
Not including "One.h" in "Two.h", and attempting to forward-declare class
One, gives the error message "Two.h(10): error C2079: 'Two::t' uses
undefined class 'One'" - of course.
Did you make Two::t a reference? (See my code below.)
Anyway. I'll take a look at forward declarations.


Here is an excellent read:

http://www.gotw.ca/gotw/007.htm

Check out the rest of the GotW archive as well :)

[...]
// * File Two.h
#ifndef TWO_H
#define TWO_H

class One; // <-- Forward declaration

class Two
{
public:
explicit Two(One & one) // <-- Take a reference
:
t(one) // <-- Remember your One
{}

private:
One & t; // <-- Keep a reference

};


Ali

Oct 10 '05 #7

P: n/a
Mtk wrote:

Victor Bazarov wrote:
Mtk wrote:
Why does the following, simple, example produce such errors?
I know it has to do with the two header files including each other
and (moreover) the usage of the classes One and Two in the "opposite"
header file... What do I have to do to make this example work?

You can't.

Let's condense your example to one file. And let's suppose the compiler
knows about classes 'One' and 'Two' somehow _apriori_.
> [...]

class One
{
public:
One();
private:
Two t;
};

> [...]

class Two
{
public:
Two();
private:
One t;
};

Now, what is the size of a class One object? As soon as you can come up
with a formula the compiler can use to calculate it, let us know.

Meanwhile, look up "forward declaration".

V


[top posting corrected] Hi!

I forgot to mention that I'm a newbie and I have no intention to make
the compiler calculate the size of any class at all (at least for now)
and, thus, I'll skip that part.
That's not a good idea; understanding this is *absolutely central* to
your understanding of why you can't do what you're trying to do.
I just want class One to have a variable of the "class Two"-type and
vice-versa, giving the requirement that each class is located in its own
header file.
Right. See above.
I'll look "forward declarations" up.


HTH,
--ag

--
Artie Gold -- Austin, Texas
http://goldsays.blogspot.com (new post 8/5)
http://www.cafepress.com/goldsays
"If you have nothing to hide, you're not trying!"
Oct 10 '05 #8

P: n/a
On Mon, 10 Oct 2005 21:08:18 +0200, Mtk wrote:


I just want class One to have a variable of the "class Two"-type and
vice-versa, giving the requirement that each class is located in its own
header file.


But then a "One" object (which contains a "Two" object containing a "One"
object) would then, within itself, contain another complete One object.
Which contains a Two which contains a One which...

The only way this can make sense is if a One object is of infinite size.

- Jay
Oct 10 '05 #9

P: n/a
Mtk
Thanks!

I'm reading on ;)

Ali Çehreli wrote:
"Mtk" <sp***********@nra.org> wrote in message
news:di**********@news.island.liu.se...
Thanks for the reply.

I may be a newbie when it comes to c++, but there must be a simpler
solution to my problem than the one you described.


There isn't a simpler solution. We must break the circular dependency
somehow.
Not including "One.h" in "Two.h", and attempting to forward-declare
class One, gives the error message "Two.h(10): error C2079: 'Two::t'
uses undefined class 'One'" - of course.


Did you make Two::t a reference? (See my code below.)
Anyway. I'll take a look at forward declarations.


Here is an excellent read:

http://www.gotw.ca/gotw/007.htm

Check out the rest of the GotW archive as well :)

[...]
// * File Two.h
#ifndef TWO_H
#define TWO_H

class One; // <-- Forward declaration

class Two
{
public:
explicit Two(One & one) // <-- Take a reference
:
t(one) // <-- Remember your One
{}

private:
One & t; // <-- Keep a reference

};


Ali

Oct 10 '05 #10

P: n/a
Mtk
But, top-posting IS the right thing to do ;)

Artie Gold wrote:
[snip]
[top posting corrected]

[snip]
Oct 10 '05 #11

P: n/a
Mtk wrote:
But, top-posting IS the right thing to do ;)

Artie Gold wrote:
[snip]
[top posting corrected]


[snip]


In which case you've revealed yourself as a troll, thereby not worthy of
further attention. Of course, like all good trolls, you'll probably morph.

Great.

--ag

--
Artie Gold -- Austin, Texas
http://goldsays.blogspot.com (new post 8/5)
http://www.cafepress.com/goldsays
"If you have nothing to hide, you're not trying!"
Oct 10 '05 #12

P: n/a
Mtk schrieb:
But, top-posting IS the right thing to do ;)


Read this:

http://www.netmeister.org/news/learn2quote2.html#ss2.3

And after that, the rest of the text.

Thomas
Oct 10 '05 #13

P: n/a

"Mtk" <sp***********@nra.org> wrote in message
news:di**********@news.island.liu.se...
Hi!

I forgot to mention that I'm a newbie and I have no intention to make the
compiler calculate the size of any class at all (at least for now) and,
thus, I'll skip that part.

I just want class One to have a variable of the "class Two"-type and
vice-versa, giving the requirement that each class is located in its own
header file.

I'll look "forward declarations" up.

Thanks


Think about this a second. You want class One to include class two, and
class two to include class One. Lets look at it in a tree type way:

class One <-- class instance
class Two <-- includes class
class One <--- includes class
class Two <-- includes class
class One <-- includes class...

you see the problem? It goes on forever.

The solution? Keep a pointer or reference to the other class. A pointer or
reference is of a fixed size, no matter the size of the object it points to.
So now we have:

class One <-- class instance
class* Two <-- includes class pointer

and that's it. And class two now looks like:

class Two <-- class instance
class* One <-- includes class pointer

Now, you may be tempted to do something like this:

class Two;

class One
{
public:
One() { TwoPoint = new Two; }
private:
Two* TwoPoint;
};

class Two
{
public:
Two() { OnePoint = new One; }
private:
One* OnePoint;
};

But that won't work either, becuase now you've just moved the recursion from
compile time to run time. See, when you create your instance of class One
it calls the constructor for class two which creates and instance of class
One which calls the constructor for class two which...

You need to rethink your design and determine what it is you actually need.
Oct 11 '05 #14

This discussion thread is closed

Replies have been disabled for this discussion.