You are here:

C++/Visual C++ user-defined #include files

Advertisement


Question
I had a .cpp file that had a lot of user-defined functions in it. When I tried to #include it in my main program using:
#include "CoolDec.cpp"
, I get error LNK1169. Can you help me?

Answer
Apologies, I accidentally posted your answer as a reject with custom explanation - doh!

Short answer:
--------------
Include a header file containing only function _declarations_ not the implementation file containing their full definitions.

Long answer:
------------

First it is usually good, and polite, practice when posting questions about errors from tools to post the _text_ of the error as well as this allows those you are beseeching to help you to see what the error is about without having to go on a hunt for such information - which may or may not be easily available. Believe it or not 'expert' does not (necessarily) imply 'encyclopedic knowledge of the details of all errors from their tool-specific identifiers for all (or any) tools every created' ! ( <grin/>)

Luckily in this case it is obvious from your description what the error is plus the description of the Microsoft linker errors are easily located with a Google search - but please do not assume this will always be the case.

Now onto what your problem is. To understand what is going on you will have to understand:

   - how #include works - a bit about the C/C++ preprocessor, compiling and linking in general will be helpful
   - the difference between a declaration and a definition and the one definition rule
   
OK so first up let us look at the steps used to build your program. First we compile each source file:

   <a.cpp> -> [Compile] -> <a.obj>

Then we link all the source files with required libraries to produce an executable:

   <all project object files> -> [link] -> <executable>
   <required libraries> ---------^

In the above depictions, and for those following,  things in < and > are, or may be considered, files and things in [ and ] show process steps.

In fact when compiling before compilation proper starts the preprocessor transforms the source file in accordance with any preprocessor directives - which are things on lines starting with # such as #include, #define, #ifdef, #ifndef, #endif etc. (and also removes comments). This makes the compilation stage pipeline look like so:

   <a.cpp> -> [Preprocess] -> <a.preprocessed> -> [Compile] -> <a.obj>

Note that a.preprocessed is usually never seen - it may exist as a temporary intermediate file or may only exists in memory. However we can ask the Visual C++ compiler to produce such a file for us with the Preprocess to a File option (/P for the cl command line compiler driver program) which is under C/C++ -> Preprocessor project properties in the Visual Studio IDE - note that the translation stops having produced the preprocessed file so no object file is produced when using this option.

So what would we expect a preprocessed source file to look if we include one file in it (note: the following is simplified for clarity!)?

Say we have a file inc.cpp containing:

   unsigned long long square(unsigned int v)
   {
       return static_cast<unsigned long long>(v)*v;
   }

Not very profound as functions go - and of course square may return incorrect results should the result overflow - which may happen if unsigned long longs are not larger than unsigned ints by enough (i.e. does not have at least twice as many bits).

Now if we include inc.cpp in a.cpp:

   char const start[] = "Before any includes";
   #include "inc.cpp"
   
   int main()
   {
       return square(3);
   }

Note: I added the Start C-string constant _only_  so there is something before the #include that will not be preprocessed away (as comments would).

Then what would you expect the pre-processed translation of a.cpp to contain? Would you maybe think it contained:

   char const start[] = "Before any includes";
   @@@ information about stuff in the module produced by compiling inc.cpp so it can all be used within a.cpp @@@
   
   int main()
   {
       return square(3);
   }

Where the line starting and ending in @@@ is some special stuff that causes a.cpp to have knowledge about what would be in the compiled object code module built by compiling inc.cpp.

Sorry, but C++ - like C - has nothing so fancy. No, the #include directive simply causes the preprocessor to open the specified file and copy its contents into the preprocessed source file it is creating at the point of the #include directive thus the preprocessed version of a.cpp would in fact look something like so:

   char const start[] = "Before any includes";
   unsigned long long square(unsigned int v)
   {
       return static_cast<unsigned long long>(v)*v;
   }
   
   int main()
   {
       return square(3);
   }

Note that further preprocessing effectively resumes at the point where the included text begins so any preprocessor directives in the included file also get preprocessed.

Now if we compile both a.cpp and inc.cpp - creating a.obj and inc.obj, then link them together with the C++ runtime library to create an executable we get the error you are asking about, the description of which (you _did_ bother to read what the error description was didn't you?) is:

   "one or more multiply defined symbols found"

(from http://msdn.microsoft.com/en-us/library/xttf5w7w(v=vs.110).aspx)

What is this about "multiply defined symbols"? Well inc.obj contains symbols (names) with external linkage from compiling inc.cpp, which will be the generated code for the square function 'tagged' with a compiled symbol form of 'square' as it is _defined_ in inc.cpp - that is it contains a full function definition with the function body defining the code steps for square.

Now a.obj contains symbols for things with external linkage from compiling a.cpp, which obviously are the generated code and compiled symbol forms for start and main, but the compiled, preprocessed version, of a.cpp also includes a definition for function square because it included the text of inc.cpp. Thus it will also contain generated code and compiled symbol for the square function. When inc.obj and a.obj are linked together the linker find _both_ contain a symbol linked to each object file's generated code for the square function - oops.

C++ has a rule called the one definition rule, or ODR, which basically means a thing can have only one definition, although the scope of one definition depends on the sort of thing. This is the whole linked progeam for things with external linkage (i.e. things seen by the linker) - which are functions and global static data that have not been specifically qualified as having internal linkage by being prefixed with the static keyword (internal linkage means internal to one translation unit - a translation unit is approximately what is compiled after a source file has been preprocessed). See the Wikipedia article for more on the ODR:

   http://en.wikipedia.org/wiki/One_Definition_Rule

OK so that is the why, but what is the fix? The fix is to only define your functions once but declare them in all other places. This requires you understand the difference between definition and declaration.

A definition provides, unsurprisingly, a complete definition of an entity. In the case of C++ objects (variables) this requires storage be allocated for the entity. In the case of C++ function definitions code will be generated, which of course requires storage to hold.

A declaration, however, merely declares that a thing exists - somewhere, possibly (probably?) not here. In most cases in C++ a definition is also a declaration - this is certainly true of your function definitions in your CoolDec.cpp file. We can declare that a thing exists as many times are we like - however all the declarations should agree and agree of course with the one definition.

However we can separate out the declaration from the definition. This is easy to do for a function: we remove the body - the part in { and } and replace it with a ;

Thus we can turn the square function definition used previously into a declaration like so:

   unsigned long long square(unsigned int v)
  | {
  |     return static_cast<unsigned long long>(v)*v;
  | }

Select the lines prefixed with | and delete them:

   unsigned long long square(unsigned int v)

and terminate the declaration statement with a ;

   unsigned long long square(unsigned int v); // square is a function defined elsewhere that can be called like so

And we have a function declaration for square. Function declarations are also known as function prototypes (from C).

In the case of objects (variables) the only time we would require a declaration is for externally linkable global static data. So if we have a global variable gCount say:

   unsigned long long gCount = 0;

You might think we could create a declaration in a similar way to a function, by removing the initialisation part but this does not work because:

   unsigned long long gCount;

Also _defines_ gCount, and in fact zero initialises it as it is static data (unlike function local automatic objects and objects created on the free store which are defined but, unless they are user defined class objects with default constructors, will be uninitialised).

This behaviour goes all the way back to earliest C (which did not have function prototypes), and the solution is to use the extern keyword:

   extern unsigned long long gCount; // gCount is an object like this but is defined elsewhere

The next question is where do you put these declarations?

Answer: in a _header_ file - commonly having an extension starting with h: .h, .hpp, .hxx etc. C++ standard library headers are odd in this respect as they have no extension at all - the thought was I think that as the ISO C++ standard defines what each standard library header should contain a clever compiler - with collusion from the preprocessor I suppose - could detect includes for standard library headers and just go ahead and define those things without requiring an actual file. I do not think anyone has actually done this so far though!

So if you do not have one already create a new file called say CoolDec.h and place in it function declarations for each of the functions in CoolDec.cpp. One way to do this is to copy CoolDec.cpp to CoolDec.h and repeatedly convert the function definitions to declaration - you can shorten the procedure I mentioned above by selecting from where the ; is to go to the closing } of the function definition and typing ; - which replaces the whole definition with a ; in one go!

You then include CoolDec.h in your other source file(s).

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.