What is different between static member function and global function?
Static class functions can
- access private and protected static data members within a class.
- access private and protected static functions.
- access private and protected per-instance data members within a class if the static function has an instance of the class.
- access private and protected per-instance functions if the static function has an instance of the class.
- shadow functions of the same name in base classes.
- access protected data and functions in base classes.
Global non-friend functions can do none of those.
When to use static member function?
Good uses of static member functions:
- Meta-programming. Real-world example is template std::char_traits. All member functions are static
- Making it a static member function gives it access to private members of the class, although a friend would suffice here too
- A protected static member function thus is accessible only to the class and classes derived from it.
Note that the last case applies to a protected static member function but not a private one. In the latter case you would just put it into the compilation unit of the class, hiding it away as an implementation detail. For a protected one though you want it to be visible, albeit in a restricted way.
A typical case of that one is "cheating" the lack of inheritance of friendship.
class B
{
friend class A;
// lots of private stuff
};
class A
{
protected:
static void callsSomePrivateMembers( B& b );
};
class AChild : public A
{
void foo( B& b );
}
void AChild::foo( B& b )
{
// AChild does not have private access to B as friendship is not inherited
// but I do have access to protected members of A including the static ones
callsSomePrivateMembers( b ); // get to call them through a back-door
}
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.
Static member functions
In general:
Require access to private members
static member functions have access to private members of the class. If you need that, you can use a static member function. You have to declare it in the header anyway to give it access, so you may as well make it a member rather than a friend. It is commonly done this way for singletons that have a getInstance() method as singleton, and classes that use a static factory method createInstance() to ensure they are created on the heap. Both of these need access to the private constructor.
Meta-programming
static member functions are very good for template meta-programming where you can pass in a class and call its method without knowing at the point of call what function will actually get invoked. This is commonly called "compile-time polymorphism" and is an important part of meta-programming. std::char_traits is based on this principle.
Restricted access
The common use of a private static member function, just so that it can be accessed only by the class, and does not itself need access to private members, is not a good use of static member functions because it is part of the implementation detail of the class, and this is better done in the anonymous namespace of the compilation unit.
However if the static member function is protected it has use as it can get called by derived classes but not by external classes.
friend functions
- Can have access to private members but need to be declared in the header anyway.
- Can be used in meta-programming as part of an "overload" however still needs to be declared in the header. (Common example is
operator<<
) - Does not work for protected access with friendship as what you are trying to do here is restrict access to the method, not what the call has access to.
How can i modify variables in static member function?
You can pass a pointer to an instance to the method:
class me {
public:
void X() { x = 1;}
void Y() { y = 2;}
static void Z(me* this_) { // fake "this" pointer
this_->x = 5 ;
this_->y = 10;
}
public:
int x, y;
};
int main() {
me M;
M.X();
M.Y();
M.Z(&M); // this works, but
// usually you call static methods like this
// me::Z(&M);
return 0;
}
Are pointers to non-static member function formally not considered pointers
The quoted statements in question seems to be validated by the following statements from the standard.
From dcl.mptr#3's note:
[ Note: See also [expr.unary] and [expr.mptr.oper]. The type “pointer to member” is distinct from the type “pointer”, that is, a pointer to member is declared only by the pointer to member declarator syntax, and never by the pointer declarator syntax. There is no “reference-to-member” type in C++. — end note ]
And from basic.compound#3:
...Except for pointers to static members, text referring to “pointers” does not apply to pointers to members...
error: invalid use of member <...> in static member function
static functions cannot access member objects. But if you make comp
a non-static member function, you can no longer pass it to sort
.
A solution is to make comp
non-static and wrap it in a lambda in the call to sort
, something like:
class Solution {
map<int, int> freq;
public:
bool comp(int a, int b){
if(a!=b){
int c1 = freq[a];
int c2 = freq[b];
if(c1!=c2)
return c1<c2;
else{
return a>b;
}
}
return a>b;
}
vector<int> frequencySort(vector<int>& nums) {
for(int i:nums){
freq[i]++;
}
sort(nums.begin(), nums.end(), [this](int a, int b) { return comp(a,b); });
return nums;
}
};
Related Topics
What's the Best Technique for Exiting from a Constructor on an Error Condition in C++
"Winapifamily.H: No Such File or Directory" When Compiling Sdl in Code::Blocks
How to Use C Source Files in a C++ Project
How to Get a List of Files in a Folder in Which the Files Are Sorted with Modified Date Time
Win32 Setforegroundwindow Unreliable
Is It Ever Not Safe to Throw an Exception in a Constructor
Visual Studio Project Out of Date
Error Lnk2005: New and Delete Already Defined in Libcmtd.Lib(New.Obj)
Reading and Writing to Usb (Hid) Interrupt Endpoints on MAC
C++ Performance of Accessing Member Variables Versus Local Variables
Understanding the Different Clocks of Clock_Gettime()
What Data Structure, Exactly, Are Deques in C++
Is Using Increment (Operator++) on Floats Bad Style
Visual Studio 2015 Gives Me Errors Upon Creating a Simple Test Console Program