Thread: about multiple file programming.

  1. #1
    Registered User
    Join Date
    Oct 2011
    Posts
    48

    about multiple file programming.

    Code:
    // Main.cpp
    
    #include<iostream>
    #include"greet.h"
    using namespace std;
    
    int main()
    {
    greetings();
    return 0;
    }
    Code:
    // Greet.h
    void greetings();
    Code:
    //Greet.cpp
    #include "greet.h"
    void greetings()
    {
    cout<<"hello world";
    }
    How is greet.cpp is included in main.cpp?
    I think #include "greet.h" will include the code from greet.h file to main.cpp and greet.cpp.
    But there is no statement to include greet.cpp in main.cpp.
    Then why greet.cpp is accessible from main.cpp?

  2. #2
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by freiza View Post
    But there is no statement to include greet.cpp in main.cpp.
    Then why greet.cpp is accessible from main.cpp?
    Good catch.... now try to compile main.cpp . You'll get a linker error.
    It is resolved by giving the compiler both files at the same time.
    (IDEs often do that for you, if the files are in the same project)
    If you're using the compiler from the command line, it'll look like "g++ greet.cpp main.cpp -o output" .

  3. #3
    Registered User
    Join Date
    Mar 2010
    Posts
    583
    The compiler just needs the function prototype to generate a call. It knows what greetings() looks like from the header -- it doesn't need to know what it does, so long as it knows how to call it (what parameters it takes, what it returns...)

    The typical way:
    A compiler will usually turn 1 source file into 1 object file. So here you have 2 source files, so you get 2 objects: say main.o and greet.o. The compiler will just generate a call to "greetings". greet.o will have the assembly code for greeting. The linker is then called on the 2 object files -- amongst other things, it will match up symbol reference and definitions as it has a view of both objects. It'll produce an executable that has both main.cpp and greetings.cpp compiled code.

    If you call e.g. "gcc main.cpp greet.cpp " gcc will probably do this under the hood.

    That's the traditional answer anyway. It's also possible that your compiler is doing whole-program optimisation and effectively joining your source files together.

    To put it another way:
    Code:
    // Main.cpp
    
    #include<iostream>
    
    void greetings(); // drop the header and just have a prototype
    using namespace std;
    
    int main()
    {
    greetings();
    return 0;
    }
    Code:
    //Greet.cpp
    void greetings()
    {
    cout<<"hello world";
    }
    All the compiler needs is the prototype. If you compiled just main.cpp in this example, it would compile, but it would fail to link because the linker couldn't find an definition of symbol greeting

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by freiza View Post
    How is greet.cpp is included in main.cpp?
    It isn't. Nor should it be.
    Quote Originally Posted by freiza View Post
    I think #include "greet.h" will include the code from greet.h file to main.cpp and greet.cpp.
    Approximately yes. The preprocessor (the thing that processes #include directives) does a straight text substitution. So, as far as the compiler is concerned, the effect of #include "greet.h" is the same as copying and pasting the content of greet.h in place of the #include directive.

    The value of the #include directive is that it is not necessary to maintain multiple copies of the contents of greet.h. Change greet.h once, and the compiler sees the changes when compiling greet.cpp and main.cpp (each has to be compiled separately, as I describe below).
    Quote Originally Posted by freiza View Post
    But there is no statement to include greet.cpp in main.cpp.
    That is exactly the way it is supposed to be.
    Quote Originally Posted by freiza View Post
    Then why greet.cpp is accessible from main.cpp?
    It isn't.

    What happens, when you are building a project, is that the compiler compiles greet.cpp to create an object file (named greet.o or greet.obj by default, depending on what compiler and operating system you are working with). It also compiles main.cpp to create another object file (named something like main.o). If any errors occur when compiling a source file, the compiler complains bitterly, and does not produce the object file.

    The object file produced from main.cpp includes information that states, in effect, that implements a function called main() that calls a function called greetings". The object file produced from greet.cpp contains the implementation of a function called greetings.

    Then another program, called a linker, is executed. It works purely with compiled object files and library files (which contain the contents of object files, in some form). For each object file, it looks for information about what functions are implemented, and what functions they call. It establishes linkages (hence its name as a linker) between points where functions are called, and the entry points of those functions. If it is able to establish a full set of linkages (i.e. every time a function is called, there is a function to be called) it outputs an executable file. That executable file is the thing you run, in your case, to print hello world.

    The important thing is that the linker does not do anything with source files. Its starting point is object files (and libraries) that the compiler produces from source files.

    Build environments (such as integrated development environments, called IDEs) orchestrate the process of invoking the compiler on each source file, to produce the required objects, then orchestrates invoking the linker to produce the executable. That is why, in IDEs, it is necessary to create some "project file" that lists all of the source files. The IDE interprets the project file, and works out how to orchestrate the invocations of compiler (as many times as needed) and the linker.

    Some compiler packages do that with a driver program. You, the programmer, enters a command line like "g++ -o greet main.cpp greet.cpp" (I'm assuming you're using the gnu compiler collection, for sake of discussion). The g++ driver executes other programs: the compiler that produces main.o from main.cpp, the compiler to produce greet.o from greet.cpp, and a linker to produce an executable named "greet" from main.o and greet.o (g++ also links against library files that contain C++ output related functions and objects, in a compiled form).

    The thing is, each source file (.cpp extension, in your case) is compiled separately. That is a requirement of the C++ standard (with a couple of exceptions that I won't describe here, as they are not relevant in your example). Just because there is code in one source file (eg an #include <iostream> followed by "using namespace std;") doesn't mean the compiler sees that code when compiling a different source file. The purpose of separate compilation is easier maintenance. If you have built a complete program, and then change one of the source files, then only the changed source file needs to be recompiled, and then the linker executed. It may not seem much to you, when you have 2 source files. It becomes very important when you work on projects that contain thousands of source files.

    Because of that separate compilation rule, your greet.cpp (as shown) will not compile. When compiling greet.cpp, the compiler encounters the name cout. You have not include'd <iostream> in greet.cpp, so the compiler - dumb beast that it is - does not know what cout is (nor does it know what namespace std is). The compiler will therefore produce a diagnostic (typically about an unknown name of cout, or words to that effect) and will not produce greet.o. Therefore, the linking phase cannot be successfully executed.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  5. #5
    Registered User
    Join Date
    Oct 2011
    Posts
    48
    You have not include'd <iostream> in greet.cpp, so the compiler - dumb beast that it is - does not know what cout is (nor does it know what namespace std is).
    When <iostream> is linked at link time. Then how does the compiler knows about cout at compile time?
    Does header files are included in compile time?

  6. #6
    Registered User
    Join Date
    Mar 2010
    Posts
    583
    <iostream> is a header file. The C library headers have ".h", the C++ library headers don't have .h (I don't know why not). Library functions can be a bit more complicated and library loading varies between toolchains -- but it's basically the same deal. Compiler sees prototype, linker sorts out finding definitions. There are some exceptions, but more on the C side than C++ (e.g. gnu builtins don't need a header).

    Are you saying that greet.cpp builds with your toolchain without including iostream? If so, what compiler are you using? It should fail to compile.

    You could remove the iostream include from main.cpp if you wanted to - it's not being used (so long as you also get rid of the "using namespace std"). You don't have to, but it's nice to keep inclusions to the minimum necessary -- makes things easier to keep track of. Probably not a worry for a small project.

  7. #7
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by freiza View Post
    When <iostream> is linked at link time. Then how does the compiler knows about cout at compile time?
    The purpose of the <iostream> header is to provide declarations of things like std::cout so the compiler can (well) compile your code.

    What happens with linking the functions and other definitions (eg of globals like std::cout) associated with <iostream> depends on how your compiler and your standard library are implemented. Different compilers work differently, and interact with linkers differently.

    Quote Originally Posted by freiza View Post
    Does header files are included in compile time?
    Sort of. Technically, there are several phases of compilation, that occur in sequence. Preprocessing (eg substitution of text from header files, to replace the #include directive) is one of the early phases of compilation. Linking occurs after all phases of compilation are complete.

    Quote Originally Posted by smokeyangel View Post
    <iostream> is a header file. The C library headers have ".h", the C++ library headers don't have .h (I don't know why not).
    It's a result of the fact that the C++ standard was required to maximise compatibility with C, but the C standard has never been required to maintain compatibility with C++.

    The C++ headers don't have a .h extension in order to avoid conflicts with future versions of the C standard. Future versions of the C standard may specify additional headers (just as the 1999 C standard introduced some headers that weren't in the 1989 C standard).

    The C standard, by convention, uses a ".h" for its standard headers. However, the C standard (to date) has been allowed to evolve without any consideration needed to ensure compatibility with C++.

    One of the mandatory requirements of the C++ standardisation effort (which led to the C++ standard of 1998) was to minimise incompatibility with C. One of the minor consequences of that was the selection of headers for the C++ library that do not have a ".h" extension. Another is that most of the C standard library is supported by the C++ standard (i.e. all of the ".h" headers in the 1989 C standard are supported in C++) although they are formally deprecated (scheduled for removal in some unspecified future version of the C++ standard).


    Quote Originally Posted by smokeyangel View Post
    Library functions can be a bit more complicated and library loading varies between toolchains -- but it's basically the same deal. Compiler sees prototype, linker sorts out finding definitions. There are some exceptions, but more on the C side than C++ (e.g. gnu builtins don't need a header).
    There is, practically, a big exception to your statement in C++ - instantiation of templates. Most of the C++ standard library is template based. There is still a lot of work to be done to get the C++ standard into a form that allows templates to play well with the separate compilation model. One current side effect of that is that large parts of the C++ library are defined (i.e. implemented) in header files, with most compilers and available implementations of the standard library. Relatively little is therefore done by the linker.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  8. #8
    Novice
    Join Date
    Jul 2009
    Posts
    568
    grumpy for President in 2012!
    Disclaimer: This post shows my ignorance at the time of its making. I claim ownership of but not responsibility for all errors in it. Reference at your own peril.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Multiple NIC network programming
    By Krulle in forum C Programming
    Replies: 1
    Last Post: 03-04-2012, 05:10 AM
  2. Need help opening multiple files (c programming)
    By awb8. in forum C Programming
    Replies: 11
    Last Post: 11-28-2010, 05:47 PM
  3. multiple file programming
    By kapil1089thekin in forum C++ Programming
    Replies: 3
    Last Post: 08-11-2010, 12:41 PM
  4. questions on multiple thread programming
    By lehe in forum C Programming
    Replies: 11
    Last Post: 03-27-2009, 07:44 AM
  5. Multiple thread and parallel programming
    By lehe in forum C Programming
    Replies: 1
    Last Post: 03-25-2009, 07:56 AM