You are here:

C++/Undefined reference when linking.

Advertisement


Question
Hi Ralph,

I am new in the C++ world, and I have problems to solve a "undefined reference to class::method" when linking my program.

The program is very simple:

#ifndef XMLIMPT_UTILS_H
#define XMLIMPT_UTILS_H

#include <xercesc/dom/DOMNode.hpp>
#include <string.h>
XERCES_CPP_NAMESPACE_USE
class XMLIMPTutils
{
 public:
 XMLIMPTutils();
 ~XMLIMPTutils();
 XMLCh* getAttributeValue(DOMNode *node, string name);
};
#endif

I have also defined XMLIMPTutils.cpp which I don't think I need to include.

I use this class from another class simply doing:

XMLIMPTutils utils;

utils.getAttributeValue(...);

and in this line I have the linking error... The more I look at the code the less I understand what could I be doing wrong. I google trying to find a possible cause for the error, but nothing works. If you could at least give a few hints to know what I'm doing wrong I will really appreciate it.

Thank you very much,
Marian.


Answer
Without knowing exactly what you are doing - what files you are compiling, which you are linking I cannot say for sure what you are doing wrong. However I strongly suspect that you have misunderstood how the C++ code sharing and "module" system works as it is different from that employed by other currently popular languages such as Java or .NET/C#.

In C and C++ building an executable is performed in two stages: First code is compiled to object code files (note that object here is a different use to object oriented programming), next these object code files are linked together to form an executable.

In addition you can have collections of object code placed together into files called libraries. In fact these are called static libraries as the code they contain are statically linked into each executable that uses them. This is in contract to dynamic libraries in which the code is not linked into each executable that uses them, but is mapped into the process space of each application that uses them at runtime. Such dynamic link libraries (called shared object libraries on some systems) are themselves a variation of an executable and need to be linked. Libraries are a useful mechanism for sharing code without having to distribute the source and require everyone to recompile it all before using it.

You are using the #include directive to share code at the source code level. The C/C++ #include directive however does _not_ work like a using or import statement in languages like C# or Java. It is merely a textual inclusion mechanism.

Before a C or C++ compilation proper starts a phase called pre-processing is performed. The pre-processor produces the content that the compiler actually compiles. The pre-processing is controlled by placing pre-processor directives in the code. These are lines in which the first non-whitespace character is a # (hash) symbol. You have used at least four such pre-processing directives in your code:

   #ifdef
   #define
   #endif
   #include

These all work at a textual level.

[you can skip the next two paragraphs on #ifdef..#endif and #define if you wish, they are an aside to your problem, and I include them only for background and completeness with the list of directives I show above.]

#ifdef..#endif are conditional compilation directives. The text between these two directives is only emitted (i.e. further pre-processed and passed to the compiler proper) if the pre-processor macro name after #ifdef is defined.

#define is used to define pre-processor macros. Anywhere in the text of the file(s) the pre-processor finds the name of a defined macro it substitutes the textual definition of the macro. Note that macros can also have parameters in which case the pre-processor will perform parameter substitution on the macro text. The compiler sees the text _after_ macro expansion. Macros are useful, but have two major drawbacks: First, because by the time compiler sees the code the pre-processor has replaced the macro names with the expanded macro text compilation errors due to macros cannot include the name of the macro. Second, the pre-processor has no idea of C or C++ syntax; when it expands a macro it will do so whatever the context without regard to scope or namespace. This can cause problems if macros use simple names that look like variables or class names or function names or class member names as it is very likely that such a name will be used without knowingly clashing with a macro name. If this happens the result is that such a name is replaced by the macro text during pre-processing, which then leads to some rather unexpected and often odd and baffling compiler errors. Your use here though is just for controlling the inclusion of the body of your header file and is in fact a standard form in C and C++. You have also followed the guideline of using long, all uppercase names for macros to help reduce name clashes to a minimum.

#include causes the pre-processor to replace the line on which the #include directive appears with the whole contents of the specified file. It then continues pre-processing at the start of the included file contents. Such a file can contain anything, and can be called anything.

Hence the code the compiler sees is the fully pre-processed text from the file being compiled and all the included files.

Most importantly #include does _not_ mean that you are using or importing any compiled implementation of the entities defined in the header file. Including file.h does not imply that a compiled version of file.cpp is to be linked with to form an executable. For a start extensions are not fixed, C++ header files commonly use .h, .H, .hpp, .hxx. C++ implementation files commonly use .cpp, .C, .cxx. C implementation files commonly use a .c suffix. There is no rule that states that if something is declared in file.h it will be defined in file.cpp (or other extension). The definition could be in someotherfile.cpp.

Assuming your program consists of the following files (or similar):

XMLIMPTutils.hpp
XMLIMPTutils.cpp
main.cpp

The two .cpp files I expect to both include XMLIMPTutils.hpp. This means they both have access to the definition of class XMLIMPTutils.

XMLIMPTutils.hpp defines the XMLIMPTutils class.

XMLIMPTutils.cpp defines the member functions of the XMLIMPTutils class.

main.cpp defines main, the program entry point and uses the XMLIMPTutils class.

I then expect you have compiled main.cpp, producing main.o or main.obj (the compiled object file).

Maybe you have also compiled XMLIMPTutils.cpp to produce XMLIMPTutils.o or XMLIMPTutils.obj, but I'll guess that you have not. So you also need to explicitly compile XMLIMPTutils.cpp.

You then have to link against _both_ main.o and XMLIMPTutils.o (or main.obj and XMLIMPTutils.obj) plus any additional libraries required (such as whatever library or libraries support the facilities of the Xerces XML parser you are using).

The exact syntax and names of object files and libraries depend on the compiler and linker you are using, usually tied to the platform you are using. Particularly MS Windows differs from Linux/UN*X.

Why is this? Well when you call XMLIMPTutils::getAttributeValue from your program all the compiler has to work with is the declaration of the member function in the class definition from the inclusion of the XMLIMPTutils.hpp header file. The compiler checks the call is consistent with the declaration and leaves a record in the object file indicating that it needs the address of the definition of this function to be provided by the linker. That is it is expected that the definition of the function is provided in some object code file (or library) and the address of this definition filled in by the linker.

If you do not give the linker the XMLIMPTutils.o or XMLIMPTutils.obj object file to link against then it finds the main.o (or main.obj) file has a reference to a function that needs to be resolved, i.e. that needs to have the address filled in, but it has not been told to link any file that contains the definition of such an externally visible function (all defined functions in C and C++ are externally visible to the linker unless specified otherwise).

Hope this helps and sorry if I missed the problem and you already know some of  

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.