Why "unresolved external"?

This is a discussion on Why "unresolved external"? within the C++ Programming forums, part of the General Programming Boards category; Hi... I've been wondering this problem for a while today. I thought it can't be this weird because it's in ...

  1. #1
    Registered User
    Join Date
    Jan 2005
    Posts
    24

    Why "unresolved external"?

    Hi...

    I've been wondering this problem for a while today. I thought it can't be this weird because it's in so small scale...but...here it is. Maybe you understand why it gives me unresolved external?

    normal_screen.h:
    Code:
    #ifndef NORMAL_SCREEN_H
    #define NORMAL_SCREEN_H
    
    #include "clock_window.h"
    
    class Normal_screen : public Clock_window {
    public:
       Normal_screen();
       ~Normal_screen();
    
       Clock_window& gClockWin();
    
    private:
       Clock_window clockWin;
    };
    
    #include "normal_screen.cpp"
    
    #endif
    normal_screen.cpp:
    Code:
    #ifndef NORMAL_SCREEN_CPP
    #define NORMAL_SCREEN_CPP
    
    Normal_screen::Normal_screen() {}
    Normal_screen::~Normal_screen() {}
    
    Clock_window& Normal_screen::gClockWin() {
       return clockWin;
    }
    
    #endif
    So...should be very simple but still it gives me two errors:
    "[Linker Error] Unresolved external 'Normal_screen::~Normal_screen()' "
    and
    "[Linker Error] Unresolved external 'Normal_screen::Normal_screen()' ".

    And yet it works if I define the constructor and destructor in file normal_screen.h like this:
    Code:
    #ifndef NORMAL_SCREEN_H
    #define NORMAL_SCREEN_H
    
    #include "clock_window.h"
    
    class Normal_screen : public Clock_window {
    public:
       Normal_screen();
       ~Normal_screen();
    
       Clock_window& gClockWin();
    
    private:
       Clock_window clockWin;
    };
    
    Normal_screen::Normal_screen() {}
    Normal_screen::~Normal_screen() {}
    
    #include "normal_screen.cpp"
    
    #endif
    So, how's that possible?? Something about linker/compiler options?

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,936
    Could it be that you are not linking the object file generated from normal_screen.cpp?
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    24
    Hmm...I haven't needed nor done that before. I have just recently moved from C to C++, so maybe that's why. How do I check that out? Although, I didn't get this error with my first class made in same way.

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,936
    Oh wait, why do you include the source file in the header?
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    Jan 2005
    Posts
    24
    I have always done so ever since I've seen that style elsewhere So, that's for the definitions of header file declarations. Like for that evil constructor and destructor and if there are something else declared in the file. Should it be done somehow else?
    Last edited by JulleH; 12-13-2009 at 09:16 AM.

  6. #6
    Registered User
    Join Date
    Oct 2006
    Location
    Canada
    Posts
    1,243
    Normally you define stuff, i.e. variables and function prototypes, in the header, then you "#include" that header when you implement those things in a ".cpp" file. So try this
    Code:
    #ifndef NORMAL_SCREEN_H
    #define NORMAL_SCREEN_H
    
    #include "clock_window.h"
    
    class Normal_screen : public Clock_window {
    public:
       Normal_screen();
       ~Normal_screen();
    
       Clock_window& gClockWin();
    
    private:
       Clock_window clockWin;
    };
    
    #include "normal_screen.cpp" // remove this, as suggested by laserlight
    
    #endif
    Code:
    #ifndef NORMAL_SCREEN_CPP
    #define NORMAL_SCREEN_CPP
    
    // #include your normal screen header here
    
    Normal_screen::Normal_screen() {}
    Normal_screen::~Normal_screen() {}
    
    Clock_window& Normal_screen::gClockWin() {
       return clockWin;
    }
    
    #endif

  7. #7
    Registered User
    Join Date
    Jan 2005
    Posts
    24
    If I remove the #include in the header file, in what point do I get the definitions for declarations from if I don't #include the .cpp file?

    I understand that like this:

    <other file> --> normal_screen.h <-- normal_screen.cpp

    Do I #include normal_screen.cpp instead of normal_screen.h in the "other file"?

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,936
    Quote Originally Posted by JulleH
    If I remove the #include in the header file, in what point do I get the definitions for declarations from if I don't #include the .cpp file?
    You compile the source file and link the object file generated. This is no different from C.

    Quote Originally Posted by JulleH
    Do I #include normal_screen.cpp instead of normal_screen.h in the "other file"?
    No, you should always include headers, not source files. There is an exception but it does not apply to C and is not relevant to you at the moment.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Oct 2006
    Location
    Canada
    Posts
    1,243
    The file "normal_screen.h" just contains some definitions and function prototypes, not, say, "actual" code, it shouldnt include any other code either (i.e. shouldnt include a .cpp file, just other .h files if necessary). Now you have a header file that, really, does nothing. It only describes what it should do at a very highlevel--name of function, arguments, return type (its "prototype"). Though there isnt any code that implements this stuff. So, you write a ".cpp" (normal_screen.cpp) file and include its corresponding header file (normal_screen.h), which describes what stuff youve "promised" to implement, and now you must do so.

    As mentioned, you dont "compile" the header file--its "useless". You compile the .cpp file, at which point the compiler will also do its magic itself by looking at any other headers it needs to take care of.

    A ".h" file can be considered as a rudimentary/basic "API" reference. If youve ever worked with Java your (hopefully!) familiar with "javadocs"--the Java API. If not then youve probably looked at API references for C++, say the "string" class to see what functions it has. You wouldnt go looking for the giant "string.cpp" file to see how its implemented--you dont care. All you want to know is whats available, i.e. its "header", which, as I said, you can think of as its API reference.

    Hopefully that clears things up a little.
    Last edited by nadroj; 12-13-2009 at 10:06 AM. Reason: Grammar fail

  10. #10
    Registered User
    Join Date
    Jan 2005
    Posts
    24
    Thanks both of you, I think this was pretty useful info for the future

    Quote Originally Posted by nadroj View Post
    As mentioned, you dont "compile" the header file--its "useless". You compile the .cpp file, at which point the compiler will also do its magic itself by looking at any other headers it needs to take care of.
    I was wondering about how do I link objects but looks like it's program's issue, not mine.

    But, still the same unresolved external error about constructor and destructor pops out. I started a new project and wrote one header and one source file. Now source file includes the header and the header is included before right before main(). It all compiles and links fine unless I try to create an object of the (one) class. Like it don't care about definitions if there aren't objects of it...don't know...this is weird

  11. #11
    Registered User
    Join Date
    Oct 2006
    Location
    Canada
    Posts
    1,243
    I was wondering about how do I link objects but looks like it's program's issue, not mine.
    When your using other libraries that require linking (i.e. using a .dll on windows or .so or .o on Linux) then you have to tell the compiler (well, the linker) what your linking with, so it can go get the actual files containing the implementations for the headers you used. For example, when you use (in C at least, maybe C++ too I dont use it as often) "math.h" (cmath in C++) then when you compile you also have to link to the math library, by passing "-lm" (Link math), because the header file doesnt contain the actual implementations, just the prototypes. So the linker will include (link) the actual code into your program when you link to it. Many common headers/libraries are linked automatically, things like "stdio.h","stdlib.h", etc. Again, I imagine a similar situation occurs with C++.

    If your still getting the problem, post all of your files in separate code blocks (as you did above), giving the file name for each and I can try copy/paste them all and run it.

  12. #12
    Registered User
    Join Date
    Jan 2005
    Posts
    24
    Uhh... I got it work with #pragma link <object file> in my test project which was cool until I tried it with my other project. Well it wasn't so cool anymore... I tried to compile the normal_screen.cpp but I got "too many warnings" that I didn't get when compiling with Borland. Probably just my compiling options that don't apply to plain compiler exe. I think I'll rewrite whole thing and compile it often to see when...or if #pragma fails.

    Is "#pragma link" what you use? What did you mean with that "-lm"? Where do you put it?

    I gotta get back to this subject later, this have taken too long for now Not the longest session, though.

  13. #13
    Registered User
    Join Date
    Oct 2006
    Location
    Canada
    Posts
    1,243
    Is "#pragma link" what you use?
    Ive never used "pragma" or any "preprocessor directives" as they are called, besides the basic ones (#include, #define, etc). I have heard about them, but not interested enough to learn what they are so I cant help with that.

    What did you mean with that "-lm"? Where do you put it?
    Hopefully I didnt confuse you, because it has nothing to do with your situation. I was just giving an example of when you have to explicitly do something when linking. I said this because you said:
    I was wondering about how do I link objects but looks like it's program's issue, not mine.
    So I was just showing that this is not always the case. I was just giving a description of what you have to do when you need to explicitly link, i.e. when using "#include <math.h>" in C (or maybe the equivalent "cmath" in C++).

    The place you put this type of option it depends on your compiler and IDE if any. For a command line compiler, ie. gcc or g++, the argument is what I said above, "-lm". So you might do "gcc -lm myProg.c". Again, this is for C. Its C++ equivalent would probably be "g++ -lm myProg.cpp". Again, these are just deeper details and not relevant to your initial question. If you want to know more then just do some reading into what linking is/does.

    As I said above, if you post all of your updated files and your exact compiler error/warnings, then I can give it a try on my side to see if I can get it working, without things like "pragma", etc.

  14. #14
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,936
    Well... nadroj's -lm example is a command line option for gcc and g++. The options may be different for Borland's compilers. This is an option to link to a library, but what you want to do here is link to an object file generated as part of your own program.

    In the case of g++, this means either passing the source file names at the command line, or compiling the source files separately and then running g++ again to produce the executable file, but with the object file names as command line arguments. This is likely to be similiar to the Borland compiler's command line interface.

    Incidentally, by default g++ would link to the math library, so -lm is not necessary.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  15. #15
    Registered User
    Join Date
    Apr 2006
    Posts
    2,053
    Quote Originally Posted by laserlight View Post
    Incidentally, by default g++ would link to the math library, so -lm is not necessary.
    Depends on the version. I've used versions that don't.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 8
    Last Post: 04-27-2006, 10:39 AM
  2. The Dreaded "Unresolved External Symbol" :-(
    By DrMario in forum C++ Programming
    Replies: 2
    Last Post: 03-25-2005, 12:43 AM
  3. Ask about these "unresolved external symbol" error
    By ooosawaddee3 in forum C++ Programming
    Replies: 1
    Last Post: 06-29-2002, 11:39 AM
  4. What's an "unresolved external"
    By Clane in forum C++ Programming
    Replies: 3
    Last Post: 03-08-2002, 08:23 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21