I have read that the difference between globals and static globals is that the global variable can be referred to in another implementation file via extern, whereas static globals are localized to only that implementation file. See these two questions for more information: [1, 2].
From what I understand, this means the that the following foo() and bar() should be linked identically. Both functions can only be used by MyClass.
//MyClass.h
Class MyClass{
private:
static void foo();
};
//MyClass.cpp
void MyClass::foo(){}
static void bar(){}
I can see foo()'s declaration being more common since it lets the header file lay out the entire class more completely (even if you can't/shouldn't use the private stuff), but is bad practice declare a function like bar() (hidden from the header file)?
For context, I am defining a WNDPROC for windows messages which needs to be static to work, but it's a rather ugly declaration and I'm not sure if I should hide it completely in the implementation file or go ahead and declare it in the header file.
static is a very horrible keyword as it has many different meanings depending on the context. static variables and static functions are completely different, and a static function in a class and a static free-function are completely different.
A static function in a class means that the function can be called without an instance of the class, but it cannot access non-static members of the class. It is a bit like a regular function, just enclosed in the class for tidiness purposes.
A static free-function has internal linkage, so it cannot be seen outside of the source file and its name can be reused in other source files.
A static class function does not have internal linkage. All class functions have external linkage. You can split the class function between header and source files whether the class function is static or not.
I recommend you read some tutorials/books to understand the many different uses of static more clearly. When you see static in a place you've not seen it before, assume nothing!
If you have a free-function which you want hide in a source file, you can declare it static as you have done so. Alternatively you can place it in an unnamed namespace.
// cpp file only
namespace
{
void hiddenfunc() {..}
}
This is similar to
static void hiddenfunc();
And it can be called in the same way (just as "hiddenfunc()"). An advantage of unnamed namespaces (a weird name, I know) is that you can also place classes and other definitions, that you only want to be visible within that source file. Just make sure you define the function body within the namespace {..} area. Don't put an unnamed namespace in a header file.
Related
So, I know static functions are functions that are local to the file. Thus, they can't be accessed from other files. Does this work for classes too? I've read a ton of controversy on how static class does not declare the class to contain purely static members and methods (which is obvious), but couldn't find anything that mentioned whether or not this would declare the class to be locally accessible to the file scope, as is more logical.
In case it doesn't, what about using an anonymous namespace, which I've heard also can be used to declare file local functions?
You can define a class in unnamed namespace as for example
namespace
{
struct A {};
}
In this case the class name will have internal linkage. That is it is visible only in the compilation unit where it is defined and all compilation units that include that definition will have their own class definitions.
As for the storage class specifier static then (7.1.1 Storage class specifiers)
5 The static specifier can be applied only to names of variables and
functions and to anonymous unions
Does this work for classes too?
No. no such 'static' keyword for class.
As an alternative to an 'anonymous namespace', you can declare a class (Foo) and its definition (implementation) entirely within a single cpp file. The only code which can use this class is the code below that declaration ...
File X.cpp:
// Foo declared
class Foo
{
public:
//...ctor
//...dtor
// etc.
}
// ... Foo defined (implemented)
Foo::etc() { ... }
// implementation of X - only X has access to Foo.
End of X.cpp.
And File X.hpp does not reference Foo.
If you subsequently discover a name collision (i.e. linker reports duplicate symbol), your only choice is to change one or the other name.
There are many Q&A's in SO about anonymous namespaces. I am careful what kinds of things I put into one, and agree they can prevent name collision.
I have used both techniques.
While implementing a class for creating/updating boxes on the screen, I wanted to add a static member function that makes sure no currently visible boxes overlap (taking its information from a static pointer array to all currently visible boxes)
My initial code had the following structure:
class Box
{
public:
// ...
static void arrangeOverlappingBoxes();
};
static void Box::arrangeOverlappingBoxes()
{
// ...
}
I was quite surprised that this generated an error C2724: 'static' should not be used on member functions defined at file scope.
With some trial, google and error, I figured out that my function definition should lose the keyword static, i.e. it should be
void Box::arrangeOverlappingBoxes()
{
// ...
}
Yet I have no clue what the rationale behind this could be. It appears to be so asymetric and confusing to have a different function header for its declaration in the class definition and its own definition. Is there any reason for this?
Your class definition (in the header file) will provide the function with whatever propreties are necessary :
static
inlined
virtual
Considering that every further object will look at your class definition using the .h then it makes sense that these properties to be defined there.
Furthermore, each function from the class will mentain it's property in the derived classes (for example you need to declare the destructor virtual only in your base class, every subsequent inheritance will take the destructor as virtual).
It makes no sense to redeclare these properties in your implementation body .
Having to declare function proprieties in both .h and .cpp files would actually lead to allot of problems.
Imagine this scenario : you declare a function as virtual in a .h file, and as static in the .cpp file. What will the compiler make that function ? virtual or static ? (or more likely a compile error , but the compiler error will just urge you to match in your .cpp file the declaration in the header. You cannot overload a function according to "static" or "virtual").
So I recently found some source code which used a particular technique(idiom?) I hadn't seen before; to put it simply; instead of using a static variable for the class in question, it used a local variable inside the classes source file.
myclass.h
class myclass {
//static int myint;
public:
myclass();
~myclass();
int count();
};
myclass.cpp
#include "myclass.h"
int myint = 0;
myclass::myclass() {
myint++;
}
myclass::~myclass() {
myint--;
}
int myclass::count() {
return myint;
}
main.cpp
#include "myclass.h"
#include <iostream>
int main() {
myclass aclass;
myclass theclass;
std::cout << theclass.count(); //outputs 2
return 0;
}
My question is, why would someone take this approach over using a static variable?
My take on it is that, since ideally the variable would only be known to the myclass class (private static), and inheritance is not of importance at all (in this case), this could stop others knowing about this variable. But that is the only advantage I can see; not sure if that would warrant it.
The same question goes for (static / non - static) member functions that are private; when inheritance is not important.
EDIT: After reading around, I'm going to make a stab that it is because some people still use C programming style...
It doesn't really matter whether you use a static member variable or a global variable or a locally declared static variable; the only important thing is that the object has to have static storage duration. Beyond that, the choice is mostly based on personal preference or coding style guidelines.
Unfortunately, this code is basically wrong. While myint is "hidden" and only directly accessible from within myclass.cpp, it still has external linkage. This means that it is accessible from other translation units (by using extern int myint in those other translation units) and its definition can conflict with other definitions of myint in other translation units.
To correct this, it should either be declared static (giving it internal linkage) or, preferably, it should be declared in an unnamed namespace,
namespace {
int myint;
}
(an object in an unnamed namespace may still have external linkage, but it is uniquely named so it cannot be used by its name from outside of the translation unit in which it is compiled.)
In your example the variable is not static and is technically visible outside the compilation unit if properly declared. If this is not intentional it can be a source of problems if another compilation unit uses the same trick on a variable with the same name (to fix this see James McNellis answer).
Assuming a properly declared static (e.g. using the unnamed namespace approach) this technique can be better than a class static because it hides completely the variable from class users. This means that if you need to add or modify that variable the clients don't even need to be recompiled (you just need to recompile the implementation .cpp file and then to relink the program). This can be a big difference if your class is used everywhere in a big project (compile just one file instead of recompiling the whole world because of a change in an internal detail).
Also if the static variable is not an int but something more complex (e.g. a templated class instance) then putting the variable in the class as a static requires to expose much more data to clients, introducing not needed dependencies.
Sometimes this unwanted dependency problem is considered so important that you can find implementation of the "compiler firewall" idiom. This hiding is sort of a partial and light version of it.
My question is, why would someone take this approach over using a static variable?
it makes sense if you have something to hide -- an int is not worth usually hiding, but a large library is. an author may also prefer to hide implementation details from clients in some cases.
regarding static functions -- i'll typically hide them if they are just free helpers, and really don't belong in, or are required to be a part of the class interface.
generally, i'll put it in the class interface simply for organizational purposes.
I have a static method in a cpp file (not in class) .
I want to use it globally without redeclaring it as extern .
In that case is it possible to use a global function pointer to this static method and
use this function pointer globally ??
It is possible to do what you want, but why would you avoid using extern when it does exactly what you are trying to emulate through a much more convoluted (and unreadable) mechanism?
The static declaration in C tells the compiler not to to add the function the symbol table. This means that the inker has no way to link that function in if needed by other modules. The function will still exists (but is invisible to the linker) so if one records the address of the function in a pointer one will be able to call the function with no problem.
So short answer is yes, it is ok.
Yes, making a public pointer while hiding the implementation is generally what you might expect in a factory style pattern.
It might be interesting to know why you say "I want to use it globally without redeclaring it as extern ."
Why is changing the declaration from static (making it available in that module only) to extern (making it available outside the module and publishing it) an action you want to avoid?
If it is static in a cpp file in the global namespace, then the function can only be used directly from within that cpp file. It is a kind of private helper function.
What you can do is to make a typedef on the function's prototype and introduce a public function that returns a pointer to the function or a table of pointers to different functions, which is often done in order to implement plug-ins and have some callbacks or api methods registered. + point is that you do not have a strong binding to the function.
the static specifier implies internal linkage.
You want static with external linkage, which does not require an explicit storage specifier. If your function is at namespace scope, simply remove the 'static' specifier. The default behavior at namespace scope is static with external linkage.
I was looking over some (C++) code and found something like this:
//Foo.cpp
namespace
{
void SomeHelperFunctionA() {}
void SomeHelperFunctionB() {}
void SomeHelperFunctionC() {}
//etc...
class SomeClass //<---
{
//Impl
};
}
SomeHelperFunction[A-Z] are functions that are only needed in that translation unit, so I understand why they're in an anonymous namespace. Similarly, SomeClass is also only required in that translation unit, but I was under the impression that you could have classes with identical names in different translation units without any sort of naming collisions provided that you didn't have a global class declaration (e.g., in a commonly included header file).
I should also mention that this particular translation unit does not include any headers that might declare a class with an identical name (SomeClass).
So, given this information, could someone please shed some light on why the original programmer might have done this? Perhaps just as a precaution for the future?
I'll be honest, I've never seen classes used in anonymous namespaces before.
Thanks!
An anonymous namespace is like the static keyword when it is applied at the global level.
An anonymous namespace makes it so you can't call anything inside the namespace from another file.
Anonymous namespaces allow you to limit the scope of what's within to the current file only.
The programmer would have done this to avoid naming conflicts. No global names will conflict in this way at linking time.
Example:
File: test.cpp
namespace
{
void A()
{
}
void B()
{
}
void C()
{
}
}
void CallABC()
{
A();
B();
C();
}
File: main.cpp
void CallABC();//You can use ABC from this file but not A, B and C
void A()
{
//Do something different
}
int main(int argc, char** argv)
{
CallABC();
A();//<--- calls the local file's A() not the other file.
return 0;
}
The above will compile fine. But if you tried to write an CallABC() function in your main you would have a linking error.
In this way you can't call A(), B() and C() functions individually, but you can call CallABC() that will call all of them one after the other.
You can forward declare CallABC() inside your main.cpp and call it. But you can't forward declare test.cpp's A(), B() nor C() inside your main.cpp as you will have a linking error.
As for why there is a class inside the namespace. It is to make sure no external files use this class. Something inside the .cpp probably uses that class.
If someone links this code and has the definition of an identical named class included and this file is linked before the other implementation you would have a name conflict.
In the C++ ISO standard (Section 2.3), you will find a rule called The One Definition Rule.
Due to the complex relationship in C++ between compilation and linking, this is not a very simple rule. Most of the details are here.
But it applies to the functions that are members of a class, because they are (at the linking level) simply functions with long names.
It applies in a slightly different way to templates, because the linker will happily discard extra definitions of template classes or functions that appear in separate translation units (source files). This means that if you provide two different definitions of the same template, your program has undefined behaviour (best case scenario: one of the definitions will be silently chosen at random).
I was under the impression that you could have classes with identical names in different translation units without any sort of naming collisions provided that you didn't have a global class declaration
Well, that's not the case. Remember that those "common" global class definitions are in header files. Those are literally included, copying that common global class definition to all translation units. If you use another way of including exactly the same class definitions in multiple translation units (eg. macro expansion), it's fine too. But if you have different definitions for the same class name, you risk undefined behavior. Link failures if you're lucky.
To answer your question directly, I think that this is to avoid linker "multiple definition" errors for static members of SomeClass. That is, suppose SomeClass is defined in a cpp file without an anonymous namespace and there are some static fields and/or static methods in it and these static members are defined next to the class definition in this very cpp-file. Then these static members get the external linkage (are present in the symbol table of the corresponding .o file as GLOBAL).
Now you have another cpp-file and you want to create another SomeClass (unrelated to that one in the first cpp-file and you may be even unaware of the existence of the first SomeClass in that first cpp-file) for your own purposes and again without an anonymous namespace. And you define a static member with the same name as a static member of the first SomeClass. And here you are: you end up with a linkage conflict.
So the author of the first cpp-file should have hidden the first SameClass inside an anounimous namespace, as the class was clearly supposed to be an implementation detail, rather than a class re-used by other people. And so its static members should not have external linkage.
So overall, what I try to say is that non-constexpr/non-inline static members of a class are just like global variables or non-inline functions. And so their linkage can be made internal using an anonymous namespace just like it can be done for global variables and functions using static keyword or again an anonymous namespace.
// .cpp file
namespace
{
struct A
{
static int i;
};
}
int A::i;