user746461
user746461

Reputation:

Different handling of .cpp and .h files?

C.h has

#ifndef UNTITLED3_C_H
#define UNTITLED3_C_H

class C {
 public:
  int F();
};

#endif //UNTITLED3_C_H

C-inl.h has

#ifndef UNTITLED3_C_INL_H
#define UNTITLED3_C_INL_H

#include "C.h"

int C::F() {
  return 1;
}

#endif //UNTITLED3_C_INL_H

main.cpp has

#include <iostream>
#include "C.h"


int main() {
  C c;
  std::cout << c.F() << std::endl;
  return 0;
}

Now I compile them with the following command, but fails.

$ g++ main.cpp C-inl.h -o main
/tmp/ccVkEs1w.o: In function `main':
main.cpp:(.text+0x1f): undefined reference to `C::F()'
collect2: error: ld returned 1 exit status

Then I rename C-inl.h to C.cpp, the compilation works.

$ g++ main.cpp C.cpp -o main
$ ./main 
1

Why does file name make a difference?

When the files are main.cpp, C.h, and C.cpp, main.cpp only includes C.h, how does the content of C.cpp kick in? When the files are main.cpp, C.h, and C-inl.h, why doesn't the content kick in?

Upvotes: 0

Views: 88

Answers (2)

Miles Budnek
Miles Budnek

Reputation: 30579

By default, GCC determines what to do with each file you specify by looking at its extension.

From the gcc(1):

file.h
    C, C ++ , Objective-C or Objective-C ++ header file to be turned into a precompiled header.

So GCC assumes you want to use "C-inl.h" and "C.h" as precompiled headers.

You can override GCC's decision using the -x flag:

g++ main.cpp -x c++ C-inl.h -o main

I would recommend against doing this though. C++ headers usually aren't compiled as separate compilation units, and doing so will make the next person to read you code very confused. "C-inl.h" is not a header. Name it what it really is: "C.cpp".

Upvotes: 0

Ripi2
Ripi2

Reputation: 7198

class C {
 public:
  int F();
};

is a declaration of function F() as a member of class C.

int C::F() {
  return 1;
}

is the definition of that function.

If you include only C.h you have NOT the definition needed at main(). The compiler knows you want that 'F()' but doesn't have a reference for its definition (the "undefined reference" error message).

Now you rename C-inl.h to C.cpp and compile it. The trick is that C.cpp does include the C.h where the declaration is done. So everything is found, compiled and linked.


Hey, C-inl.h includes C.h and I told g++ to compile C-inl.h!!
Yeah, but gcc docs remarks how g++ takes the .h extension:

file.h

C, C++, Objective-C or Objective-C++ header file to be turned into a precompiled header (default)

And you need that file to be handled as a .cpp file, not precompiled header.

Upvotes: 0

Related Questions