开发者

How can static functions be useful?

开发者 https://www.devze.com 2023-01-31 13:38 出处:网络
I don\'t开发者_如何学Python get all these keywords.Specially this one static.An example of how important it is and how it used would be wonderful.Making a member function static allows you to call the

I don't开发者_如何学Python get all these keywords. Specially this one static. An example of how important it is and how it used would be wonderful.


Making a member function static allows you to call the function without creating the class object.

class MyClass
{
    int i;
    static MyClass *ptr;
    static MyClass* getInstance()
    {
        if(NULL == ptr)  
        {
            ptr = new MyClass();
        }
        return ptr;
    }

};

MyClass* MyClass::ptr = NULL;

int main()
{
    MyClass *ptr = MyClass::getInstance();

}

Check out the Singleton pattern for more information on how it can be helpful.


static member functions are just like regular functions.

class Sample
{
    public:
        static void DoWork() 
        {
           cout << "Static Member Function"<< endl;
        }
};

//access
Sample::DoWork();

Output:

Static Member Function

You can treat them just like regular functions, that means, you can pass them to other functions which accept only regular function as argument, like this:

typedef void (*Worker)();
void Fun(Worker worker)
{
    //call here just like regular function
    worker(); //note: class name is not needed even if you pass static member function!
}

//pass static member function!!
Fun(Sample::DoWork);

Output:

Static Member Function


There are multiple uses for the static keyword, it does different things based on where you use it.

http://msdn.microsoft.com/en-us/library/s1sb61xd.aspx

When you declare a variable or function at file scope (global and/or namespace scope), the static keyword specifies that the variable or function has internal linkage. When you declare a variable, the variable has static duration and the compiler initializes it to 0 unless you specify another value.

When you declare a variable in a function, the static keyword specifies that the variable retains its state between calls to that function.

When you declare a data member in a class declaration, the static keyword specifies that one copy of the member is shared by all instances of the class. A static data member must be defined at file scope. An integral data member that you declare as const static can have an initializer.

When you declare a member function in a class declaration, the static keyword specifies that the function is shared by all instances of the class. A static member function cannot access an instance member because the function does not have an implicit this pointer. To access an instance member, declare the function with a parameter that is an instance pointer or reference.


Static classes and class members are used to create data and functions that can be accessed without creating an instance of the class. The advantage is that you don't need to instantiate the class to use methods or properties.

An example of when to use a static class might be for utility functions such as converters (e.g. Fahrenheit to Celcius). This type function doesn't change irregardless of any object or data.

In C# you can call a static method like this:

double F, C = 0

// TempConverter converter = new TempConverter();  <-- NOT NEEDED FOR STATIC

F = TempConverter.CelsiusToFahrenheit("100.0");

C = TempConverter.FahrenheitToCelcius("212.0");

Here is how the static class and methods are defined:

public static class TemperatureConverter {

  public static double CelsiusToFahrenheit(string temperatureCelsius) {
    .. conversion code..
  }
  public static double FahrenheitToCelsius(string temperatureFahrenheit)  {
    .. conversion code..
  }
}


There are two types of static functions: class/struct member, and non-member. I guess you're wondering about the former (as it's more confusing)...

static member functions

If we contrast four functions:

class X
{
    ....
    int non_static_member_f(X& a) { ... }
    static int static_member_f(X& a) { ... }
    friend int non_member_friend_f(X& a) { ... }
};

int non_member_f(X& a) { ... }

And given:

X x, arg; 

We can write:

  • x.non_static_member_f(arg) - x is an existing X object instance - made accessible via the this pointer. The function has full access to all private/protected/public static/non-static members of X for operations on x and arg.

  • X::static_member_f(arg) can be invoked with a single X argument - if the function didn't specify an X argument, then it could be called with no existing X objects. It has full access to all private/protected/public static of X, and can access any non-static members on arg.

  • non_member_friend_f(arg) has the same access as X::static_member_f(arg), but is not scoped inside X (i.e. you don't need to call it with the X:: prefix, Koenig lookup resolves differently).

  • non_member_f(arg) can only access the public members of arg, and has no special privileges.


For completeness: static non-member functions differ from non-static in having internal linkage, which means they're not callable from other translation units but won't clash with any same-named function in those translation units.


Static functions are very useful when implementing so-called Named Constructors.

Imagine a Point class which can be either constructed from rectangular coordinates (X/Y) or polar coordinates (radius and angle):

class Point {
public:
  Point(float x, float y);     // Rectangular coordinates
  Point(float r, float a);     // Polar coordinates (radius and angle)
  // ERROR: Overload is Ambiguous: Point::Point(float,float)
};

int main()
{
  Point p = Point(5.7, 1.2);   // Ambiguous: Which coordinate system?
  ...
}

This can be solved very nicely using static functions which create Point objects; such functions are called named constructors since they act like a constructor (they produce a new object) but they can have a descriptive name:

class Point {
public:
  // These static methods are the so-called "named constructors"
  static Point rectangular(float x, float y) { return Point(x, y); }
  static Point polar(float radius, float angle) { return Point(radius*std::cos(angle), radius*std::sin(angle)); }

  // ...
private:
  Point(float x, float y) : x_(x), y_(y) { }
  float x_, y_;
};

Clients of the class can now use these named constructors to create readable, unambiguous code:

int main()
{
  Point p1 = Point::rectangular(5.7, 1.2);   // Obviously rectangular
  Point p2 = Point::polar(5.7, 1.2);         // Obviously polar
}

Furthremore, named constructors can be used to make sure that objects of a class are always allocated with new (so that you know that you can always call delete on them). See FAQ [16.21] for more information.


static class member functions are useful:

  1. For implementing the Factory Method Pattern
  2. For implementing the Singleton Pattern
  3. For loose decoupling of functions that may polute the behaviour of the class. ( Functions not necessarily members can be declared static... but even better they could be totally classic functions!) cf S.R.P.
  4. Can be used as a function to be passed as a plain C function pointer so as to inter-operate with C code...

static functions are useful: 1. to avoid duplicate code redefinition while compiling. A static function will be redefined for each cpp unit it is included in.

And I think there are tons of other useful cases I don't remember of right now :-)


The answer from martona is a good overview of static. Relating to static members, I think Tony covers it pretty well.

The mental model I use when it comes to member functions is to consider how they might be modeled in 'C':

class A
{
public:
  void mbr_1 ();
  void mbr_2 () const;
  void mbr_3 () volatile;
  void mbr_4 () const volatile;
  static void mbr_5 ();
};

Might be implemented as:

struct A { };
void mbr_1 (A * const this);
void mbr_2 (A const * const this);
void mbr_3 (A volatile * const this);
void mbr_4 (A const volatile * const this);
void mbr_5 ();

All the funcitons are members and so have appropriate 'access' to private members. The non static members have a 'this' pointer, and it is that which provides the access to a specific instances members. The static member doesn't have such a pointer and this is why we cannot access any non static members.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号