Reputation: 1746
I have been reading the 2nd edition of A Tour of C++ by Bjarne Stroustroup and in section 3.2 on Separate Compilation, he mentions translation units.
A
.cpp
file that is compiled by itself (including theh
files it#includes
) is called a translation unit. A program can consist of many thousand translation units.
I tried to follow along the prior chapters and build up the code for Vector
and wrote out the .h
and .cpp
files for this diagram also in the same section.
vector.h
class Vector
{
public:
Vector(int s) : elem{new double[s]}, sz{s} {}
int size();
double &operator[](int i);
private:
int sz; // the number of elements
double *elem; // pointer to the elements
};
vector.cpp
#include "vector.h"
double &Vector::operator[](int i)
{
return elem[i];
}
int Vector::size()
{
return sz;
}
int main()
{
}
user.cpp
- own implementation to test things out
#include "vector.h"
#include <iostream>
int main() {
Vector v{4};
std::cout << v.size() << std::endl;
}
When I built the object file for vector
with g++
, I got a linker error and I was able to resolve this with writing a main
function in Vector.cpp
.
$ g++ vector.cpp
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x1b): undefined reference to `main'
collect2: error: ld returned 1 exit status
Based on the diagram above, that appears in the same section of the book, it seems to me that user.cpp
would also need its own main
function as I can't compile it without main
as I get the same error as above but I can't compile successfully without adding vector.cpp
in the command to g++
.
However, when I compile both, I get an error that I have multiple main
functions.
$ g++ vector.cpp user.cpp
/usr/bin/ld: /tmp/ccX6Gtco.o: in function `main':
user.cpp:(.text+0x0): multiple definition of `main'; /tmp/ccdQHbRR.o:vector.cpp:(.text+0x3a): first defined here
collect2: error: ld returned 1 exit status
user
without this error? Because g++ user.cpp
complains that size
isn't defined.main
function because that's the only way to compile it?user.cpp
is with vector.cpp
, is this compilation different from the definition of a translation unit? Isn't this a different relationship compared to what is shown in the diagram where both arrows point to vector.h
?This question says that:
A single translation unit can be compiled into an object file, library, or executable program.
main
in either case?Upvotes: -1
Views: 102
Reputation: 76889
Does every translation unit need to have a main function?
No, on the contrary, there must be exactly one definition of the global main
function in exactly one translation unit.
Anything else wouldn't make much sense anyway: main
is the starting point for the program execution (well except for dynamic initialization of non-local static storage duration objects). There can't be two starting points.
When I built the object file for vector with g++, I got a linker error and I was able to resolve this with writing a main function in Vector.cpp.
That's because by-default (i.e. without options set) g++
assumes that you built your program in one single invocation and that you list all source files that, individually, will be treated as translation units of the program as arguments.
It then doesn't generate an object file (or at least doesn't keep them around), but instead links all translation units (object files) together into an executable directly. By-default the resulting executable will be named a.out
.
Usually there are two steps to generating the C++ executable: First compilation of each translation unit into an object file and then linking of all object files together into the final executable that implements the program consisting of all the translation units made up by the object files. The standard invocation of g++
combines the two steps in one.
That's also why GCC complains when you invoke g++ vector.cpp user.cpp
and you add main
to both translation units. With this invocation GCC will treat vector.cpp
as one translation unit and user.cpp
as another, both of them together making up the program for which GCC will generate an executable. main
musn't be defined twice and therefore there is an error if you defined it in both translation units.
In order to only perform the first step and compile a single source file as single translation to an object file you need to give g++
the -c
option:
g++ -c vector.cpp
This will now compile vector.cpp
as a single translation unit into an object file vector.o
without invoking a linker.
You then need to similarly compile user.cpp
as single translation unit into an object file with
g++ -c user.cpp
And then you can built the final executable for the program consisting of both translation units by calling g++
without arguments and the object files as arguments:
g++ vector.o user.o
GCC will call the linker to link the two object files into one executable. Again, by-default the generated executable will be named a.out
. The name of any output can be changed with the -o
option.
Of course, as stated at the beginning, there must be only one definition of main
in the program. So for this method to work, you must not have it defined in both the vector.cpp
and the user.cpp
translation unit. It is equivalent to the all-in-one-step invocation g++ vector.cpp user.cpp
.
Upvotes: 3