problem with sequence of include files

Discussion in 'C++' started by Tio, Oct 9, 2006.

  1. Tio

    Tio Guest

    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 ?
    Tio, Oct 9, 2006
    #1
    1. Advertising

  2. Tio

    Gavin Deane Guest

    Tio wrote:
    > 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
    Gavin Deane, Oct 9, 2006
    #2
    1. Advertising

  3. Tio

    Salt_Peter Guest

    Tio wrote:
    > 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.
    Salt_Peter, Oct 9, 2006
    #3
  4. Tio

    Tio Guest


    > 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?
    Tio, Oct 9, 2006
    #4
  5. Tio

    Gavin Deane Guest

    Tio wrote:
    > > 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?


    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>
    <contents of dialog1.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
    Gavin Deane, Oct 9, 2006
    #5
  6. Tio

    Salt_Peter Guest

    Tio wrote:
    > > 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?


    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.
    Salt_Peter, Oct 9, 2006
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Danny Anderson
    Replies:
    5
    Views:
    495
    Victor Bazarov
    Aug 15, 2003
  2. Rolf Magnus
    Replies:
    2
    Views:
    598
    Karl Heinz Buchegger
    Nov 28, 2003
  3. web4all
    Replies:
    0
    Views:
    3,130
    web4all
    May 11, 2006
  4. stef mientki
    Replies:
    13
    Views:
    633
    stef mientki
    Oct 20, 2007
  5. Andreas Bogenberger
    Replies:
    3
    Views:
    899
    Andreas Bogenberger
    Feb 22, 2008
Loading...

Share This Page