problem with sequence of include files

T

Tio

I have project in MFC(vc++) . There are files and classes:

classes:dialog1,dialog2,aaa,bbb

----------------------
main.cpp
---------------------
#include "mainfrm.h"
#include "dialog1.h"
#include "dialog2.h"

dialog1 dlg1;
dialog2 dlg2;
_______________________

-----------------------
dialog1.cpp
----------------------
#include "aaa.h"
#include "dialog1.h"

-----------------------
dialog2.cpp
----------------------
#include "bbb.h"
#include "dialog2.h"

-----------------------
aaa.cpp
----------------------
#include "aaa.h"
#include "dialog1.h"

-----------------------
bbb.cpp
----------------------
#include "bbb.h"
#include "dialog2.h"
_____________________

in 'aaa.h' occurs:
dialog1 dlg;

in 'dialog1.h' occurs
aaa work;

and

in 'bbb.h' occurs:
dialog2 dlg;

in 'dialog2.h' occurs:
bbb work;

And how could be sequence of include files that there aren't any
errors. Now I always get:
error C2501: 'bbb' : missing storage-class or type specifiers
error C2501: 'aaa' : missing storage-class or type specifiers
during compling file :main.cpp
I try many combinations and always I got some errors like that.
How should I write this ?
 
G

Gavin Deane

Tio said:
I have project in MFC(vc++) . There are files and classes:

classes:dialog1,dialog2,aaa,bbb

----------------------
main.cpp
---------------------
#include "mainfrm.h"
#include "dialog1.h"
#include "dialog2.h"

dialog1 dlg1;
dialog2 dlg2;
_______________________

-----------------------
dialog1.cpp
----------------------
#include "aaa.h"
#include "dialog1.h"

-----------------------
dialog2.cpp
----------------------
#include "bbb.h"
#include "dialog2.h"

-----------------------
aaa.cpp
----------------------
#include "aaa.h"
#include "dialog1.h"

-----------------------
bbb.cpp
----------------------
#include "bbb.h"
#include "dialog2.h"
_____________________

in 'aaa.h' occurs:
dialog1 dlg;

in 'dialog1.h' occurs
aaa work;

and

in 'bbb.h' occurs:
dialog2 dlg;

in 'dialog2.h' occurs:
bbb work;

And how could be sequence of include files that there aren't any
errors. Now I always get:
error C2501: 'bbb' : missing storage-class or type specifiers
error C2501: 'aaa' : missing storage-class or type specifiers
during compling file :main.cpp
I try many combinations and always I got some errors like that.
How should I write this ?

Is this your problem?
http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.11

Gavin Deane
 
S

Salt_Peter

Tio said:
I have project in MFC(vc++) . There are files and classes:

classes:dialog1,dialog2,aaa,bbb

----------------------
main.cpp
---------------------
#include "mainfrm.h"
#include "dialog1.h"
#include "dialog2.h"

dialog1 dlg1;
dialog2 dlg2;
_______________________

-----------------------
dialog1.cpp
----------------------
#include "aaa.h"
#include "dialog1.h"

-----------------------
dialog2.cpp
----------------------
#include "bbb.h"
#include "dialog2.h"

-----------------------
aaa.cpp
----------------------
#include "aaa.h"
#include "dialog1.h"

-----------------------
bbb.cpp
----------------------
#include "bbb.h"
#include "dialog2.h"
_____________________

in 'aaa.h' occurs:
dialog1 dlg;

in 'dialog1.h' occurs
aaa work;

and

in 'bbb.h' occurs:
dialog2 dlg;

in 'dialog2.h' occurs:
bbb work;

And how could be sequence of include files that there aren't any
errors. Now I always get:
error C2501: 'bbb' : missing storage-class or type specifiers
error C2501: 'aaa' : missing storage-class or type specifiers
during compling file :main.cpp
I try many combinations and always I got some errors like that.
How should I write this ?

Look at main.cpp. It includes mainfrm.h. Then dialog1.h is included.
Stop there.
dialog1 is a class declared in dialog1.h. Since this class needs to
access the declaration for aaa, then dialog1.h needs to include aaa.h.
Including aaa.h in dialog1.cpp is therefore meaningless.
But.. there is a bigger problem here.

What is puzzling is that you seem to be describing a dialog2 which has
a component bbb which has a component dialog2, which in turn would have
a bbb, etc...

The compiler won't let you do that since, even if you forward declare
an incomplete type, it can't generate an instance of it when you invoke
the other class's ctor. Which is a good thing. Infinite, recursice
allocations are not allowed. If they were, you'ld run out of memory.

You can, however, declare a pointer. Or rather, a const pointer to the
wrapping class. That way, work can modify the dialog and no-one can
accidentally come along and invalidate the precious pointer to Dialog.

#include <iostream>

class Dialog; // foward declaration, incomplete type
class Work
{
Dialog* const d; // const ptr to dialog container
public:
Work(Dialog* p) : d(p) { }
Dialog* const getDialogPtr() const { return d; }
};

class Dialog
{
Work w;
public:
Dialog() : w(this) { }
Work getWork() const { return w; }
};

int main()
{
Dialog dialog;
std::cout << "address of dialog = " << &dialog << std::endl;
Work work = dialog.getWork();
std::cout << "address of member work = " << &work << std::endl;
std::cout << "work.getDialogPtr() = " << work.getDialogPtr() <<
std::endl;

return 0;
}

I still say its a bad idea. Whatever work needs dialog to get done
should not be work's responsability. In effect, work should be a member
function of dialog, not a member.
Lastly, MFC knows nothing about C++. A "class" in MFC is not even a
true class as defined in C++. If you really need to use an MS GUI that
does support both C++classes and templates, i'ld strongly suggest
considering WTL (the T stands for template, something else MFC knows
nothing about). If you do try it, look at the size of the resulting
executable.
 
T

Tio

Look at main.cpp. It includes mainfrm.h. Then dialog1.h is included.
Stop there.
dialog1 is a class declared in dialog1.h. Since this class needs to
access the declaration for aaa, then dialog1.h needs to include aaa.h.
Including aaa.h in dialog1.cpp is therefore meaningless.

so how should I do this ?
But.. there is a bigger problem here.
What is puzzling is that you seem to be describing a dialog2 which has
a component bbb which has a component dialog2, which in turn would have
a bbb, etc...


I simplified my project,deleted some relationships. Now is :

//main.cpp
#include "main.h"
#include "dialog2.h"
#include "dialog1.h"

//dialog1.cpp
#include "work1.h"
#include "dialog1.h"
//dialog1.h
class dialog1{
public:
work1 w;
}

//dialog2.cpp
#include "work2.h"
#include "dialog2.h"
//dialog2.h
class dialog2{
public:
work2 w;
}

//work1.cpp
#include "work1.h"

//work2.cpp
#include "work2.h"

and still I have errors :
Compiling...
main.cpp
....dialog2.h(38) : error C2501: 'work2' : missing storage-class or type
specifiers
....dialog1.h(41) : error C2501: 'work1' : missing storage-class or type
specifiers

now there aren't two classes that both know about each other, but
problem doesn't disappear.
Any idea?
 
G

Gavin Deane

Tio said:
so how should I do this ?




I simplified my project,deleted some relationships. Now is :

//main.cpp
#include "main.h"
#include "dialog2.h"
#include "dialog1.h"

//dialog1.cpp
#include "work1.h"
#include "dialog1.h"
//dialog1.h
class dialog1{
public:
work1 w;
}

//dialog2.cpp
#include "work2.h"
#include "dialog2.h"
//dialog2.h
class dialog2{
public:
work2 w;
}

//work1.cpp
#include "work1.h"

//work2.cpp
#include "work2.h"

and still I have errors :
Compiling...
main.cpp
...dialog2.h(38) : error C2501: 'work2' : missing storage-class or type
specifiers
...dialog1.h(41) : error C2501: 'work1' : missing storage-class or type
specifiers

now there aren't two classes that both know about each other, but
problem doesn't disappear.
Any idea?

Let's simplify your example:

//dialog1.cpp
#include "work1.h"
#include "dialog1.h"

//dialog1.h
class dialog1{
public:
work1 w;
}

....dialog1.h(41) : error C2501: 'work1' : missing storage-class or type
specifiers

The #include directive tells the compiler to "paste in" the text of the
header at that point in the source file. So when the compiler gets to
it, dialog1.cpp looks like:

<contents of work1.h>
From what you've shown, I can see that dialog1.cpp looks like

<contents of work1.h>
class dialog1{
public:
work1 w;
}

Two problems here. First, that class definition should end with a
semicolon. Second, can you see my difficulty in knowing what you might
have done wrong? I have no idea what your compiler is seeing because I
done know anything about the contents of work1.h. This is against the
guidelines in FAQ 5.8
http://www.parashift.com/c++-faq-lite/how-to-post.html#faq-5.8
which are designed to get you the best help in the quickest way.
Without knowing the contents of work1.h, it is impossible to know what
the exact problem is. All I can guess is that work1.h does not define
the symbol work1, but then the compiler has already told you that. Fix
whatever is wrong in work1.h (or post a minimal, complete example here
- see FAQ 5.8 - if you can't fix it yourself) and your problem will go
away.

You do seem to have a more fundamental problem though. A header file
should be a complete compileable entity in its own right. For every
header file you ever write, you should be able to create a source file
that contains nothing but the line
#include "my_header.h"
and that source file should compile with no errors. Let's imagine you
had a file called blank.cpp and it contained nothing but
#include "dialog1.h"

The compiler would see blank.cpp as

class dialog1{
public:
work1 w;
};

[I have added the semicolon at the end of the class definition]

On compiling blank.cpp, the compiler will clearly object because all it
can see is those four lines and it has nothing to tell it what work1
is. Your solution to that has been to add #include "work1.h" at the top
of blank.cpp [assuming whatever problem you currently have in work1.h
has been fixed], which means that each and every time you include
dialog1.h, you must remember to include work1.h first. However, by my
rules above, you aren't allowed to add anything to blank.cpp. You need
to add #include "work1.h" to dialog1.h. So now you have

// dialog1.h
#include "work1.h"
class dialog1{
public:
work1 w;
};

// blank.cpp
#include "dialog1.h"

And when compiling blank.cpp, the compiler sees

<contents of work1.h>
class dialog1{
public:
work1 w;
};

Assuming, as we are, that the contents of work1.h correctly defines
work1, that will now compile. Whenever you need to use the dialog1
class, you just include dialog1.h and it compiles. The burden of having
to remember to also include work1.h first has been removed.

Gavin Deane
 
S

Salt_Peter

Tio said:
so how should I do this ?




I simplified my project,deleted some relationships. Now is :

//main.cpp
#include "main.h"
#include "dialog2.h"
#include "dialog1.h"

//dialog1.cpp
#include "work1.h"
#include "dialog1.h"
//dialog1.h
class dialog1{
public:
work1 w;
}

//dialog2.cpp
#include "work2.h"
#include "dialog2.h"
//dialog2.h
class dialog2{
public:
work2 w;
}

//work1.cpp
#include "work1.h"

//work2.cpp
#include "work2.h"

and still I have errors :
Compiling...
main.cpp
...dialog2.h(38) : error C2501: 'work2' : missing storage-class or type
specifiers
...dialog1.h(41) : error C2501: 'work1' : missing storage-class or type
specifiers

now there aren't two classes that both know about each other, but
problem doesn't disappear.
Any idea?

Yes i have an idea, a class declaration requires a semicolon. You
should have determined that from the error generated. The compiler is
unable to determine where the declaration for work1 is (since it too is
probably missing a semicolon. So the compiler stops attempting to
process dialog2.h since it can't find a valid, complete declaration for
work2 in work2.h. same for the error at dialog1.h(41).
Do you not see "missing storage-class or type specifiers" errors?

so...
// dialog2.h declaration
#include "work2.h"
class dialog2
{
public:
work2 w;
}; // <- semicolon

// dialog2.cpp implementation
#include "dialog2.h"

Now, i don't know what work# looks like, but i'ld strongly suggest
constructors so you don't have to screw around with unitialized
objects. Always, always initialize your members.

So assuming that work2 has a deffault ctor declared work2()...

// dialog2.h declaration
#include "work2.h"

class dialog2
{
work2 w; // private == safety
public:
dialog2(); // def ctor declaration, modify as required
}; // <- semicolon required, its a declaration

// dialog2.cpp implementation
#include "dialog2.h"

dialog2::dialog2() : w() // init list initializes all members
{
} // <- no semicolon, its a definition

Note how its redundant to include work2.h in dialog.cpp. The header
already has it. Gavin's post explains that nicely -
<quote>
the #include directive tells the compiler to "paste in" the text of the
header
<unquote>
Thats valid for both translation units (cpp files) and headers. While a
compiler is not aware of the header files and all it sees is the
translation units, the headers that are injected into the translation
units must be self sufficient. A user-type like work2{...}; must be
declared before it can be used.

The next question you might ask is: how the hell does a compiler
prevent including a header multple times? Thats where include guards
come in. I didn't write them in the class above so as to concentrate on
the previous issue. The proper way to write dialog2.h would be as
follows:

// dialog2.h declaration
#ifndef DIALOG2_H /* if dialog2.h was not already included */
#define DIALOG2_H /* set this flag to prevent multple inclusions */

#include "work2.h"
class dialog2
{
work2 w;
public:
dialog2();
};

#endif /* end include guard DIALOG2_H */

And it doesn't matter what constant is used as long as its consistant
and does not start with one or two underscores.
 

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
473,995
Messages
2,570,226
Members
46,815
Latest member
treekmostly22

Latest Threads

Top