Member function with static linkage
The keyword static
has several different meanings in C++, and the code you've written above uses them in two different ways.
In the context of member functions, static
means "this member function does not have a receiver object. It's basically a normal function that's nested inside of the scope of the class."
In the context of function declarations, static
means "this function is scoped only to this file and can't be called from other places."
When you implemented the function by writing
static void Foobar::do_something() {} // Error!
the compiler interpreted the static
here to mean "I'm implementing this member function, and I want to make that function local just to this file." That's not allowed in C++ because it causes some confusion: if multiple different files all defined their own implementation of a member function and then declared them static
to avoid collisions at linking, calling the same member function from different places would result in different behavior!
Fortunately, as you noted, there's an easy fix: just delete the static
keyword from the definition:
void Foobar::do_something() {} // Should be good to go!
This is perfectly fine because the compiler already knows that do_something
is a static
member function, since you told it about that earlier on.
Static member functions error; How to properly write the signature?
I'm guessing you've done something like:
class Foo
{
static void Bar();
};
...
static void Foo::Bar()
{
...
}
The "static void Foo::Bar
" is incorrect. You don't need the second "static
".
Why can static member function definitions not have the keyword 'static'?
There's ambiguity alright. The same definition need not be for a member function at all.
Consider this:
namespace foo {
static void bar();
}
static void foo::bar() {
}
foo::bar
is required to be defined with the same linkage specifier.
For member functions, however, static
is not a linkage specifier. If it was allowed, the correctness of the definition of foo::bar
will be very very context dependent on what foo
is. Disallowing static
in fact eases the burden on the compiler.
Extending it to members in general, as opposed to just member functions, is a matter of consistency.
Declaring a static member with static linkage
If the goal is just to not have to create a .cpp
file, the
simplest solution would probably be to wrap the static data
member in an inline static member function. In other words,
something like:
struct Transport
{
static ServiceType& service()
{
static ServiceType theData;
return theData;
}
};
Of course, you'll have to use the syntax service()
, rather
than just service
, to access it.
Why can a static member function only be declared static inside the class definition and not also in its own definition?
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").
static member function with C language binding?
C++11 7.5/4 "Linkage specifications"
A C language linkage is ignored in determining the language linkage of
the names of class members and the function type of class member
functions.
So your example is valid in the sense that it's not malformed or an error, but the extern "C"
should have no effect on S::foo()
or T::foo()
.
Related Topics
Compile-Time Map and Inverse Map Values
Linear Index Upper Triangular Matrix
Virtual Dispatch Implementation Details
How Much Overhead Is There in Calling a Function in C++
Performance Penalty for Working with Interfaces in C++
Large 2D Array Gives Segmentation Fault
Templates: Template Function Not Playing Well with Class's Template Member Function
How to Implement Lock Free Map in C++
What Is a Good Easy to Use Profiler for C++ on Linux
Memory-Efficient C++ Strings (Interning, Ropes, Copy-On-Write, etc)
Implementing the Visitor Pattern Using C++ Templates