CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8
  1. #1
    Join Date
    Dec 2010
    Posts
    907

    Would this cause a link time error?

    Code:
    #include "stdafx.h"
    #include "A.h"
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    
    	int v = A::b.getValue();
    	return 0;
    }
    Code:
    #pragma once
    
    #include "B.h"
    
    class A
    {
    public:
    	A();
    	~A();
    	
    
    public:
    	static B b;
    };
    Code:
    #pragma once
    class B
    {
    public:
    	B();
    	~B();
    
    public:
    	int getValue() { return 1; }
    };
    Would this cause a link time error anyways? I've tested it, it says link time error
    saying A::b is not defined.

    How can I define b, it seems failing to be allocated in memory somewhere.
    Thanks
    Jack
    Last edited by lucky6969b; August 7th, 2015 at 02:45 AM.

  2. #2
    Join Date
    Dec 2010
    Posts
    907

    Re: Would this cause a link time error?

    Okay,
    I can use
    static int getValue();

    Update:
    Whoops, wrong... Not good to declare methods as static, what is the alternative?
    Last edited by lucky6969b; August 7th, 2015 at 02:43 AM.

  3. #3
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Would this cause a link time error?

    design awkwardness aside(*), yes, static members should be defined somewhere (**) ... usually, this is done in A's cpp file:

    Code:
    // A.cpp
    
    B A::b; // assuming a default constructor
    (*) at a higher level, what are you trying to do ?
    (**) exceptions are static constexpr's and static const integers of which (basically) you don't take the address ( or more technically, any object that's not "ODR-used" )
    Last edited by superbonzo; August 7th, 2015 at 02:49 AM.

  4. #4
    Join Date
    Dec 2010
    Posts
    907

    Re: Would this cause a link time error?

    I try to avoid passing the same single-copy object around.
    Why is it not good?
    Thanks
    Jack

  5. #5
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Would this cause a link time error?

    actually, I was referring to your original post ( that you edited later ) where the static B member of A was accessed from B's own constructor ... that was very awkward

    your current code is still awkward because it seems you want a B singleton exposed through an A's public static member ... this is not how you usually define singletons ...

    regarding why singletons are usually not a good idea, please, refer to one of the many already discussed singleton related threads in this very form ..

  6. #6
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,164

    Re: Would this cause a link time error?

    Hi Jack,

    Firstly, I’d like to say that I very much agree with what superbonzo has written. However, I’d also like to answer why the linker is complaining.

    Consider the following class:

    Code:
    class A {
    public:
      A(){
        ++instanceCounter_;
      }
     
      ~A() {
        --instanceCounter_;
      }
     
      int numInstances() {
        return instanceCounter_;
      }
     
    private:
      static int instanceCounter_;
    };
    When the compiler is compiling for a static variable, you have to keep in mind that it intends that there is only one instance of that variable. I’m guessing that what you are thinking the above will do, is that if in a main.cpp file, you include “A.h” and then proceed to create four instances of class A, then what will happen is that there would only be one instance of instanceCounter_ and its value would be 4. Well, if the compiler treated “static int instanceCounter_” as a definition and not a declaration, then you would be correct. However, there is a very good reason why they compiler does not accept the above declaration of instanceCounter_ as a definition.

    Consider the following scenario, let’s say you have two compilation units, B.cpp and main.cpp. Both B.cpp and main.cpp include “A.h”. Now remembering that instanceCounter_ needs to be static and therefore the linker can only allow one definition of instanceCounter_, then in which output object file should the compiler place the definition of A::instanceCounter_? Now before you answer “just one, but it doesn’t matter which”, consider that the compilation stage is not allowed to assume what will be done with the resulting object files – for all it knows multiple applications/libraries could be being built at the same time using the object files that it outputs; thus, it can’t assume that it can pick which of the object files in which to place the definition of A::instanceCounter_. At the same time, it can’t include the definition in both object files because the result of attempting to link both object files together would end in failure with a linker error stating that there are multiple definitions of A::instanceCounter_. The only sensible thing the compiler can do, is treat A::instanceCounter_ purely as a declaration and not a definition and therefore not include a definition of A::instanceCounter_ in either of the two object files, but instead expect that it will be provided by another object file. Therefore, what you are missing is that the static variable needs to be defined in a cpp file. Now enter A.cpp:

    Code:
    //A.cpp – contains the definition of A::instanceCounter_;
    int static A::instanceCounter_ = int(0); //Initialise the static variable to 0
    Now if you compile and link A.cpp, B.cpp and main.cpp then the linker will be happy, because A.cpp contains the definition of instanceCounter_.

    In short, a variable that is declared static, must be explicitly defined in one, and only one compilation unit in order for a compile and link to succeed.

  7. #7
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Would this cause a link time error?

    I know I'm nitpicking but

    Quote Originally Posted by PredicateNormative View Post
    At the same time, it can’t include the definition in both object files because the result of attempting to link both object files together would end in failure with a linker error stating that there are multiple definitions of A::instanceCounter_.
    in theory, it could; the compiler could "mark" the static as shared among tu's and let the linker strip off the duplicates ( as it does with the weak symbols generated by inlines and templates ).

    the real reason ( or at least one of the possible real reasons ) is that non local static variables have stricter initialization order requirements than local statics ( hence, the compiler needs to know the per tu order of definitions, rather than just assuming that ODR applies and it's order independent, as it is in the inline functions case ).

    For example, consider the following

    Code:
    class A {
    public:
      A(){
        ++instanceCounter();
      }
    
      ~A() {
        --instanceCounter();
      }
    
      int numInstances() {
        return instanceCounter();
      }
    
    private:
      static inline int& instanceCounter()
      {
        static int instanceCounter_ = 0;
    
        return instanceCounter_;
      }
    };
    ignoring init order, this is essentially equivalent to your code sample above, yet it does not require to define anything in an "explicit" tu

  8. #8
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,164

    Re: Would this cause a link time error?

    Quote Originally Posted by superbonzo View Post
    I know I'm nitpicking but
    That's alright, I'm going to nitpick back.

    .
    .
    .
    .
    .
    .
    .
    .
    .
    .
    .
    .
    .
    .

    Alright then, I just spent the last 10 minutes writing an app to prove that your example will produce one static instance per tu... only to find out that it doesn't and indeed they are effectively equivalent... the mind boggles lol.

    Well, I leant something today, so thanks

    EDIT:
    Apparently I have to spread some rep around before I can give you some again. So, count this comment as an "I owe you".

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured