Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Header files #include problem

Header files #include problem

Scheduled Pinned Locked Moved C / C++ / MFC
helpquestion
12 Posts 5 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • O Offline
    O Offline
    Oliver123
    wrote on last edited by
    #1

    Two classes X and Y. I want to #include X.h in Y.h I want to #include Y.h in X.h I can do one, but not both. I understand that there is a "self-referencing" situation happening here. What I don't understand is how I can work around this. What am I trying to do? Instances of both X and Y are created by an instance of class Z. I would like X to have a pointer to instance of Y. I would like Y to have a pointer to instance of X. In X I have a function that takes Y* as a parameter. Z executes it and that's how I get Y* into X. In Y I have a function that takes X* as a parameter. Z executes it and that's how I get X* into Y. This works when Y.h is included in X.h OR This works when X.h is includd in Y.h It will not work with both #includes. Ideas? Work arounds? Thanks

    D B 2 Replies Last reply
    0
    • O Oliver123

      Two classes X and Y. I want to #include X.h in Y.h I want to #include Y.h in X.h I can do one, but not both. I understand that there is a "self-referencing" situation happening here. What I don't understand is how I can work around this. What am I trying to do? Instances of both X and Y are created by an instance of class Z. I would like X to have a pointer to instance of Y. I would like Y to have a pointer to instance of X. In X I have a function that takes Y* as a parameter. Z executes it and that's how I get Y* into X. In Y I have a function that takes X* as a parameter. Z executes it and that's how I get X* into Y. This works when Y.h is included in X.h OR This works when X.h is includd in Y.h It will not work with both #includes. Ideas? Work arounds? Thanks

      D Offline
      D Offline
      David Crow
      wrote on last edited by
      #2

      Oliver123 wrote:

      What I don't understand is how I can work around this.

      Check out the #pragma once directive.


      "Normal is getting dressed in clothes that you buy for work and driving through traffic in a car that you are still paying for, in order to get to the job you need to pay for the clothes and the car and the house you leave vacant all day so you can afford to live in it." - Ellen Goodman

      "To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne

      1 Reply Last reply
      0
      • O Oliver123

        Two classes X and Y. I want to #include X.h in Y.h I want to #include Y.h in X.h I can do one, but not both. I understand that there is a "self-referencing" situation happening here. What I don't understand is how I can work around this. What am I trying to do? Instances of both X and Y are created by an instance of class Z. I would like X to have a pointer to instance of Y. I would like Y to have a pointer to instance of X. In X I have a function that takes Y* as a parameter. Z executes it and that's how I get Y* into X. In Y I have a function that takes X* as a parameter. Z executes it and that's how I get X* into Y. This works when Y.h is included in X.h OR This works when X.h is includd in Y.h It will not work with both #includes. Ideas? Work arounds? Thanks

        B Offline
        B Offline
        Bram van Kampen
        wrote on last edited by
        #3

        What you need is a Foward Declaration. e.g. class Y; class X{ . . . Y* m_pY; . . . }; class Y{ . . . X* m_pX; . . . }; The First Line: class Y; informs the compiler that thrte will be a class named Y, whatever it's nature. You cannot use the class at that stage, because the compiler does not know what's in it, and for instance the size in memory would be unknown. The compiler has enough information though, to allow you to use a pointer to an instance of type class Y . This method og allowing a forward declaration was included in the language precisely to get around the deadlock situation you described. Hope this is of help. :)

        LateNightsInNewry

        O 1 Reply Last reply
        0
        • B Bram van Kampen

          What you need is a Foward Declaration. e.g. class Y; class X{ . . . Y* m_pY; . . . }; class Y{ . . . X* m_pX; . . . }; The First Line: class Y; informs the compiler that thrte will be a class named Y, whatever it's nature. You cannot use the class at that stage, because the compiler does not know what's in it, and for instance the size in memory would be unknown. The compiler has enough information though, to allow you to use a pointer to an instance of type class Y . This method og allowing a forward declaration was included in the language precisely to get around the deadlock situation you described. Hope this is of help. :)

          LateNightsInNewry

          O Offline
          O Offline
          Oliver123
          wrote on last edited by
          #4

          I did this, and it successfully compiled. Passed a pointer to class Y into class X. Passed a pointer to class X into class Y. When I try to use Y* in X, the compiler says Y is undefined. When I try to use X* in Y, the compiler says X is undefined. So, when using forward references, where does the compiler eventually get the definition of Y so it can be used as Y* in X? Is there some type of ordering of what is presented to the compiler? Thanks

          P B 2 Replies Last reply
          0
          • O Oliver123

            I did this, and it successfully compiled. Passed a pointer to class Y into class X. Passed a pointer to class X into class Y. When I try to use Y* in X, the compiler says Y is undefined. When I try to use X* in Y, the compiler says X is undefined. So, when using forward references, where does the compiler eventually get the definition of Y so it can be used as Y* in X? Is there some type of ordering of what is presented to the compiler? Thanks

            P Offline
            P Offline
            Peter Weyzen
            wrote on last edited by
            #5

            Just to add a little more confusing detail: If you just reference the object by pointer or reference (either inside the class data or in a function declaration) then you can get away with just a forward reference. In these cases the size of the object is fixed -- the size of a pointer. And since you're not using the other class, it needs to know nothing about the functions in it... If you declare an instance of class or override an class -- then you must include the header. In this case, the compiler needs to actually know something about the object to compile (like the size of the other class, what virtual functions it has, ... ) Sorry if this is a little confusing. The gist is -- don't include the header until the object is actually used. And always try to use a forward declaration.... if you can. Oh, and always use "#pragma once" too

            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Peter Weyzen Staff Engineer [SoonR Inc -- PC Power delivered to your phone](http://www.soonr.com)

            V 1 Reply Last reply
            0
            • P Peter Weyzen

              Just to add a little more confusing detail: If you just reference the object by pointer or reference (either inside the class data or in a function declaration) then you can get away with just a forward reference. In these cases the size of the object is fixed -- the size of a pointer. And since you're not using the other class, it needs to know nothing about the functions in it... If you declare an instance of class or override an class -- then you must include the header. In this case, the compiler needs to actually know something about the object to compile (like the size of the other class, what virtual functions it has, ... ) Sorry if this is a little confusing. The gist is -- don't include the header until the object is actually used. And always try to use a forward declaration.... if you can. Oh, and always use "#pragma once" too

              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Peter Weyzen Staff Engineer [SoonR Inc -- PC Power delivered to your phone](http://www.soonr.com)

              V Offline
              V Offline
              Vaclav_
              wrote on last edited by
              #6

              Peter Weyzen wrote:

              Sorry if this is a little confusing. The gist is -- don't include the header until the object is actually used. And always try to use a forward declaration.... if you can.

              I always get myself into trouble by not keeping track of #include statements and try to resolve it by adding my #include statement into stdafx.h header. Sometime it makes even more mess. My question - is this a good way to code in MFC ? For extreme - could one do all class forward declarations in stdafx.h?

              P B 2 Replies Last reply
              0
              • V Vaclav_

                Peter Weyzen wrote:

                Sorry if this is a little confusing. The gist is -- don't include the header until the object is actually used. And always try to use a forward declaration.... if you can.

                I always get myself into trouble by not keeping track of #include statements and try to resolve it by adding my #include statement into stdafx.h header. Sometime it makes even more mess. My question - is this a good way to code in MFC ? For extreme - could one do all class forward declarations in stdafx.h?

                P Offline
                P Offline
                Peter Weyzen
                wrote on last edited by
                #7

                I think you'd do the best service if you "crafted" each header to include only what it needs. It should be able to stand on it's own.... But you should decide what that is -- for your project. There's no perfect way to do it. One of my bosses would always complain about how long the project took to build. So, being the boss that he was, he demanded that all headers got included into stdafx... this caused them all to be precompiled and sped up the build. The downside was that everything got built all the time as you changed headers.... It wasn't a particularly great style -- not something I thought highly of -- but it was the way we did things at that job. Do what's works for you and your work environment.

                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Peter Weyzen Staff Engineer [SoonR Inc -- PC Power delivered to your phone](http://www.soonr.com)

                1 Reply Last reply
                0
                • O Oliver123

                  I did this, and it successfully compiled. Passed a pointer to class Y into class X. Passed a pointer to class X into class Y. When I try to use Y* in X, the compiler says Y is undefined. When I try to use X* in Y, the compiler says X is undefined. So, when using forward references, where does the compiler eventually get the definition of Y so it can be used as Y* in X? Is there some type of ordering of what is presented to the compiler? Thanks

                  B Offline
                  B Offline
                  Bram van Kampen
                  wrote on last edited by
                  #8

                  Your compiler reads your source file line by line. the #include directive means exactly that: 'include' It is conceptually as if at that point the entire file to be included is copied and pasted to the location of the #include directive. What the compiler digests is your cpp file, with at all levels the #include directives removed and replaced by the contents of the file to be included. This is one of the functions of the Pre-Processor. (Note that the compiler proper knows nothing about header files, it compiles the cpp file after the Pre-Processor has expanded it.) So, the ordering of things depends on the ordering of your #include file directives, and on the order of the statements in your header files. Similar Sample with Line Numbers: 1 class X; 2 class Y{ 3 X* m_pX; 4 }; 5 class X{ 6 Y* m_pY; 7 }; The Class X is forward declared at line 1 The forward Declaration is used in line 3 The Class Declaration for class Y is completed on line 4 The Class Declaration for class X starts on line 5; The Class declaration for class X uses class Y on line 6.This can be done without a forward declaration, because class Y is fully declared after line 4. The Class Declaration for X completes at line 7. If you try to do anything of the kind of *m_pX before the end of line 7 you get an error, you dereference something that has not been completely declared. Hope this clarifies things. N.B. A Note about '#pragma once' It is not difficult to end up with a 'spagetti' of include files, and at some stage inevitibly a file would be included twice. This gives all sorts of problems, and the compiler usually chokes on this, but this situation is often hard to unravel. The directive '#pragma once' tells the preprocessor to check if the particular file has already been included, and, if so to ignore the #include directive. Best of Luck :)

                  Bram van Kampen

                  O 1 Reply Last reply
                  0
                  • B Bram van Kampen

                    Your compiler reads your source file line by line. the #include directive means exactly that: 'include' It is conceptually as if at that point the entire file to be included is copied and pasted to the location of the #include directive. What the compiler digests is your cpp file, with at all levels the #include directives removed and replaced by the contents of the file to be included. This is one of the functions of the Pre-Processor. (Note that the compiler proper knows nothing about header files, it compiles the cpp file after the Pre-Processor has expanded it.) So, the ordering of things depends on the ordering of your #include file directives, and on the order of the statements in your header files. Similar Sample with Line Numbers: 1 class X; 2 class Y{ 3 X* m_pX; 4 }; 5 class X{ 6 Y* m_pY; 7 }; The Class X is forward declared at line 1 The forward Declaration is used in line 3 The Class Declaration for class Y is completed on line 4 The Class Declaration for class X starts on line 5; The Class declaration for class X uses class Y on line 6.This can be done without a forward declaration, because class Y is fully declared after line 4. The Class Declaration for X completes at line 7. If you try to do anything of the kind of *m_pX before the end of line 7 you get an error, you dereference something that has not been completely declared. Hope this clarifies things. N.B. A Note about '#pragma once' It is not difficult to end up with a 'spagetti' of include files, and at some stage inevitibly a file would be included twice. This gives all sorts of problems, and the compiler usually chokes on this, but this situation is often hard to unravel. The directive '#pragma once' tells the preprocessor to check if the particular file has already been included, and, if so to ignore the #include directive. Best of Luck :)

                    Bram van Kampen

                    O Offline
                    O Offline
                    Oliver123
                    wrote on last edited by
                    #9

                    The fog begins to clear a bit. Question: In your example, all the statements are in one file. However, VC++ creates individual header files for each class. To emulate what you have shown, we would have to control of the order in whch the header files are presented to the compiler. Correct? Can we give the compiler the header.h files in the order it needs them while still maintaining the very convenient system of one header file per class? Is there a way to do this? Thanks

                    B 1 Reply Last reply
                    0
                    • V Vaclav_

                      Peter Weyzen wrote:

                      Sorry if this is a little confusing. The gist is -- don't include the header until the object is actually used. And always try to use a forward declaration.... if you can.

                      I always get myself into trouble by not keeping track of #include statements and try to resolve it by adding my #include statement into stdafx.h header. Sometime it makes even more mess. My question - is this a good way to code in MFC ? For extreme - could one do all class forward declarations in stdafx.h?

                      B Offline
                      B Offline
                      Bram van Kampen
                      wrote on last edited by
                      #10

                      Vaclav_Sal wrote:

                      For extreme - could one do all class forward declarations in stdafx.h?

                      Vaclav_Sal wrote:

                      My question - is this a good way to code in MFC ?

                      Answers: No!, and Bad Practice! Keeping Track of things is one of these things we have to do when writing code. Planning your Code and File Organisation is an important part of your design process. Regards, :)

                      Bram van Kampen

                      1 Reply Last reply
                      0
                      • O Oliver123

                        The fog begins to clear a bit. Question: In your example, all the statements are in one file. However, VC++ creates individual header files for each class. To emulate what you have shown, we would have to control of the order in whch the header files are presented to the compiler. Correct? Can we give the compiler the header.h files in the order it needs them while still maintaining the very convenient system of one header file per class? Is there a way to do this? Thanks

                        B Offline
                        B Offline
                        Bram van Kampen
                        wrote on last edited by
                        #11

                        ///////////////////////////// // Header File X.H #pragma once; class Y; //Fwd Decl, Add by Hand class X{ Y* m_pY; }; //////////////////////////// //////////////////////////// // Header File Y.H #pragma once; class X;; //Fwd Decl, Add by Hand class Y{ X* m_pX; }; //////////////////////////// //////////////////////////// // Z.CPP #include "stdafx.h" #include "X.H" #include "Y.H" // Both Classes X and Y are properly declared here //////////////////////////// This way things will work whatever the order of the includes. One of the Forwards will technically be redundant, in this example the forward 'class X' This does not matter, the compiler simply ignores redundant forwards. Note however, that X.H and Y.H on their own are never usable. :sigh: For this reason it is probably better to declare both classes in the same header. When you use ClassWizzard to create a new class, the wizzard gives default file names based on the class name. You can change these names, and can direct the generated file to any of your choice. And, Yes, you can direct more than one class definition to a single header file. Hope this helps, :)

                        Bram van Kampen

                        O 1 Reply Last reply
                        0
                        • B Bram van Kampen

                          ///////////////////////////// // Header File X.H #pragma once; class Y; //Fwd Decl, Add by Hand class X{ Y* m_pY; }; //////////////////////////// //////////////////////////// // Header File Y.H #pragma once; class X;; //Fwd Decl, Add by Hand class Y{ X* m_pX; }; //////////////////////////// //////////////////////////// // Z.CPP #include "stdafx.h" #include "X.H" #include "Y.H" // Both Classes X and Y are properly declared here //////////////////////////// This way things will work whatever the order of the includes. One of the Forwards will technically be redundant, in this example the forward 'class X' This does not matter, the compiler simply ignores redundant forwards. Note however, that X.H and Y.H on their own are never usable. :sigh: For this reason it is probably better to declare both classes in the same header. When you use ClassWizzard to create a new class, the wizzard gives default file names based on the class name. You can change these names, and can direct the generated file to any of your choice. And, Yes, you can direct more than one class definition to a single header file. Hope this helps, :)

                          Bram van Kampen

                          O Offline
                          O Offline
                          Oliver123
                          wrote on last edited by
                          #12

                          I combined the header files and everything works. First I created class X with X.cpp and X.h Then created class Y with Y.cpp, but changed the default header file to X.h. So both class X and class Y had their headers in the same file. Forward reference worked. Both X and Y are created in Z. Z then passes pointers to X and Y by invoking a function of X and a function of Y. In X, a pointer to Y allows me to execute Y functions. In Y, a pointer to X allows me to execute X functions. The only peculiarity is when creating functions in Y. I right click Y in the class window in the workspace, then select ADD MEMBER FUNCTION. The new function is declared in class Y in file X.h, but the implememtation goes into X.cpp. Deleting the skeleton implementtion in X, and pasting it into Y.cpp solves the problem. Thanks for the help.

                          1 Reply Last reply
                          0
                          Reply
                          • Reply as topic
                          Log in to reply
                          • Oldest to Newest
                          • Newest to Oldest
                          • Most Votes


                          • Login

                          • Don't have an account? Register

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • World
                          • Users
                          • Groups