0

I am new to c++ so forgive me if this question doesn't make much sense, but I have the follow files:

// main.cpp
#include <iostream>
#include <fstream>
using namespace std;

#include "second.h"

int main () {
    string filename;
    cin >> filename;
    ifstream fileIn;

    if( !openFile(fileIn, filename) ) {
        cerr << "Could not open file \"" << filename << "\"" << endl;
        cerr << "Shutting down" << endl;
        return -1;
    }

    return 0;
}

// second.h
#include <string>
#include <fstream>

bool openFile(ifstream& inFile, string filename);

// second.cpp
#include "second.h"
#include <iostream>
#include <fstream>
using namespace std;

bool openFile(ifstream& inFile, string filename) {
    inFile.open(filename);

    if (inFile.fail()) {
        return false;
    }
    return true;
}

My question is, why does c++ need so much redundancy? Why do I need to #include <iostream> and <fstream> for both main.cpp and second.cpp if main already calls them? Why does the header files also need to include the function parameters (ifstream& inFile, string filename)? This just seems like a waste, when the function in second.cpp already asks for it. Why not just say openFile(); in the header and have function in second.cpp as for the parameters? This may just be more of a rant, but I just want a deeper understanding as to why theses redundancies are needed. Or is there something I am missing?

  • 1
    C++ has a model of *separate compilation*. So main.cpp and second.cpp are compiled entirely independently of each other. When the compiler is compling main.cpp it is not looking at second.cpp and vice versa. So what one file includes has no effect of what the other file needs to include. This was done (I guess) for reasons of efficiency when C was being invented and C++ uses the same approach. More modern languages tend to compile the whole source code as one unit. – john Nov 07 '20 at 21:05
  • what you call "redundancy" is just a line you have to type. With header guards there is no actual redundancy during compilation (of a single translation unit) – 463035818_is_not_an_ai Nov 07 '20 at 21:06
  • As presented, `second.cpp` won't even compile. The very first thing it does is pull in `second.h`, which uses two types, `ifstream`, and `string`, that it doesn't yet know anything about. – WhozCraig Nov 07 '20 at 21:07
  • @WhozCraig Thank for for catching these things. I just missed including them during the copy/paste. – TylerSingleton Nov 07 '20 at 21:16

3 Answers3

2

The general issue

The reason you have to include relevant headers in each .cpp file is because such .cpp files are compiled separately and independently; in more formal parlance: They constitute different "translation units". See also:

What is a "translation unit" in C++

Sometimes, when multiple translation units must all include several headers, we define a common single header file which containing all these inclusions - so that the .cpp files only need to include the common header to get all their necessary inclusions. Remember that inclusion is basically pasting the contents of the included file instead of the #include directive, and parsing that file as well, so an include-in-an-include is the same as making a direct #include.

Your specific example

In your specific example,

  • You actually don't need to #include <iostream> in second.cpp, because you only seem to be using constructs from <fstream>.
  • You don't need to #include <fstream> in any of the .cpp files, because they #include "second.h", which in turn includes <fstream> (so that it gets included when they are compiled, as well).
einpoklum
  • 118,144
  • 57
  • 340
  • 684
0

You can include #include <iostream> and <fstream> into second.h and then include it to main.cpp. Don't forget to use Include Guard, when you link to header files.

nexan_pro
  • 87
  • 1
  • 7
  • 3
    Not just a case of 'you can', you should include and in second.h. Otherwise second.h will fail to compile if it is the first include. It's a bad situation when the header files you write have to be used in a certian order. Each header file should stand on its own. – john Nov 07 '20 at 21:02
  • Thank you for catching that. I do have it included, I just forgot to put it in this example. – TylerSingleton Nov 07 '20 at 21:12
0

main.cpp uses std::ifstream, std::cin, and std::cerr, this is why your example requires the includes in main.cpp.

You should read about #include directive to understand this idea and what's going on during compilation.

Peter
  • 2,796
  • 1
  • 17
  • 29