Thread: Simple C++ Compilation Question

  1. #1
    Registered User
    Join Date
    Nov 2005
    Posts
    88

    Simple C++ Compilation Question

    I just had a pretty simple c++ compilation question. I am curious whether my knowledge is flawed, or if this is another symptom of a non-standard MSVC++ 6 compiler.

    In file test.h, I declare extern const std::string strTest.
    In file main.cpp I define const std::string strTest = "Test". Main.cpp does not include test.h.
    other.cpp includes test.h. It uses strTest in one of its functions.

    When I compile, the linker says strTest is undefined.

    My understanding was every cpp file in a project gets compiled. Since there is a definition for strTest in main.cpp, it is a declared identifier. The external designation in test.h should be paired with the definition in main.cpp. Is this the case, or is my knowledge of the standard c++ compilation flawed?

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Are you certain main.cpp is included in the project? If it was not then you could get that message. Also, strTest should be a global within the main.cpp file and not local to a particular function and we can't tell by what you've provided.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    Registered User
    Join Date
    Nov 2005
    Posts
    88
    Good points. main.cpp was definitely a part of the project. Also, strTest was defined globally in main.cpp. I got it to compile correctly by including Test.h in main.cpp, but I just did not believe that should have been necessary. I wanted to see if I am correct in believing that.

  4. #4
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    I've got MSVC++ 6 here and I tried what you did with a quick sample and got the same linker error. I removed the const declaration from the file where it was declared and also from the header where it was defined and it then compiled/linked successfully however. Hmmm...
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  5. #5
    Registered User
    Join Date
    Nov 2005
    Posts
    88
    Would you agree this seems to be a non-standard compilation practice (nothing new with the MSVC++ 6 compiler)?

  6. #6
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    In file main.cpp I define const std::string strTest = "Test".
    C++ global variables are, by default, static. (Unlike C.) Try using
    Code:
    extern const std::string strTest = "Test";
    (Since you assign a value to the variable, the compiler knows that this is the point of definition.)

    [edit]
    One way to tell if it's a problem with MSVC is to try compiling it with different compilers, such as Dev-C++.
    [/edit]
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  7. #7
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Quote Originally Posted by dwks
    C++ global variables are, by default, static. (Unlike C.)
    Incorrect. C++ global variables have external linkage just like in C. In fact, all the extern keyword does is turning it into a declaration instead of a definition. (Though, I think, the assignment might counteract that effect.)

    However, const variables, if not explicitely declared extern either by an extern specifier in the definition itself or a previous declaration using the extern specifier, have internal linkage and strTest is thus not visible to other.cpp.

    If the OP had included test.h in main.cpp, a previous declaration with an extern specifier would have been visible to the compiler and the linkage would have been extern.

    The information I refer to is in 3.5 of the standard, particularly 3.5.3. According to this information, VC++6 is correct in its behaviour.
    I should note, though, that I'm referring to the last draft version of the standard and that details might have changed.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  8. #8
    Registered User
    Join Date
    Nov 2005
    Posts
    88
    So I am correct in external definition being global as long as the variable being declared is not a constant? However, for a constant, it requires an external flag to indicate global definition?

    What is the underlying logic behind having that distinction between const and non-const variables? At first glance it seems counter-intuitive.

  9. #9
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    It allows you to put constant definitions into header files without worrying that you get multiple definition errors.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  10. #10
    Registered User
    Join Date
    Nov 2005
    Posts
    88
    I changed the definition to indiciate that the constant should be externally linked. I did this by using the extern const strTest = "Test" in main.cpp. The project compiles correctly. However, when I assign strTest to a static member variable of a class (the static member definition occurs in the .cpp file), it fails to assign the data "Test" to the variable. I put a break point on the assignment line to discover the data contained by strTest is believed to be "". If I place the definition in the .h file, removing the extern, this issue does not occur. However, I want the definition to exist in the cpp file. Is there any reason strTest would be "" despite the constant definition assigning "Test" to it?

    Edit: Further testing by placing a breakpoint at the line of code that assigns "Test" to strTest occurs AFTER the static member variable assignment. Why is this the case? Aren't const assignments suppposed to have precedence?

    Thank you.
    Last edited by mercury529; 07-28-2006 at 02:47 PM.

  11. #11
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    C++ global variables are, by default, static. (Unlike C.)
    Incorrect. C++ global variables have external linkage just like in C. In fact, all the extern keyword does is turning it into a declaration instead of a definition. (Though, I think, the assignment might counteract that effect.)
    Why does this not compile if the #if 1 is changed to #if 0, then?
    Code:
    // extern1.cpp
    
    #include <iostream>
    
    #if 1
    extern
    #endif
        const std::string strTest = "Test";
    
    void other(void);
    
    int main(void) {
        std::cout << strTest << std::endl;
        other();
    
        return 0;
    }
    Code:
    // extern2.cpp
    
    #include <iostream>
    
    extern const std::string strTest;
    
    void other(void) {
        std::cout << strTest << std::endl;
    }
    Output with #if 1:
    Code:
    Test
    Test
    Output with #if 0:
    Code:
    /tmp/ccqhsUOf.o(.text+0xa): In function `other()':
    : undefined reference to `strTest'
    I could be mistaken. Could you post the relevent section of the standard?
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  12. #12
    System Novice siavoshkc's Avatar
    Join Date
    Jan 2006
    Location
    Tehran
    Posts
    1,246
    I am confuzed, that code compiles and runs correctly in my VC++6. Does sevice packs change the compiler? I have no SP installed.

    All files should include "extern const std::string strTest" directly or indirectly (by including a header). In one and only one of the files a value can be assigned to it. And I made a class with a static var and assigned strTest to it and printed it to screen. It worked!
    Learn C++ (C++ Books, C Books, FAQ, Forum Search)
    Code painter latest version on sourceforge DOWNLOAD NOW!
    Download FSB Data Integrity Tester.
    Siavosh K C

  13. #13
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Quote Originally Posted by dwks
    Why does this not compile if the #if 1 is changed to #if 0, then?
    I believe CornedBee was referring to the distinction between global variables and const variables in terms of default linkage. I believe you mentioned "global variables" in your post, when in fact you most certainly wanted to say "const variables".

    The later do have internal linkage by default on C++.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  14. #14
    System Novice siavoshkc's Avatar
    Join Date
    Jan 2006
    Location
    Tehran
    Posts
    1,246
    Code:
    //main.cpp
    #include<iostream>
    #include"class.h"
    
    int main(){
    	
    	std::cout<<clat::basment<<std::endl;
    	return 0;
    }
    Code:
    //externc.cpp
    #include<string>
    extern const std::string i ="Heel the world";
    Code:
    //class.cpp
    #include"class.h"
    
    std::string clat::basment = i;
    Code:
    //externc.h
    extern const std::string i;
    Code:
    //class.h
    #ifndef CLASS
    #define CLASS
    #include<string>
    #include"externc.h"
    class clat{
    public:
    	static std::string basment;
    };
    
    #endif //CLASS
    Last edited by siavoshkc; 07-30-2006 at 11:19 PM.
    Learn C++ (C++ Books, C Books, FAQ, Forum Search)
    Code painter latest version on sourceforge DOWNLOAD NOW!
    Download FSB Data Integrity Tester.
    Siavosh K C

  15. #15
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Sorry, my wording was ambiguous.
    Quote Originally Posted by dwks
    C++ global variables are, by default, static.
    I meant to say "C++ const variables are, by default, static."
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Simple question regarding variables
    By Flakster in forum C++ Programming
    Replies: 10
    Last Post: 05-18-2005, 08:10 PM
  2. Simple class question
    By 99atlantic in forum C++ Programming
    Replies: 6
    Last Post: 04-20-2005, 11:41 PM
  3. Simple question about pausing program
    By Noid in forum C Programming
    Replies: 14
    Last Post: 04-02-2005, 09:46 AM
  4. simple question.
    By InvariantLoop in forum Windows Programming
    Replies: 4
    Last Post: 01-31-2005, 12:15 PM
  5. simple fgets question
    By theweirdo in forum C Programming
    Replies: 7
    Last Post: 01-27-2002, 06:58 PM