Archive for February, 2008

When to use "static"?

Contents

  • Introduction.
  • A C++ reference on “static”.
  • “Const” vs. “Static”.
  • C# “static”.
  • Conclusion.
  • References.

Introduction

This article is the outcome of a question that popped up in my mind when I was dealing with Factories and (therefore, together with) Singletons. One of the technologies I’m currently working on is the Composite Application Block (CAB) and the Smart Client Software Factory (SCSF). I mentioned this as in the CAB/SCSF there are functional classes called Services, which are allocated in containers (called WorkItems, but I mention the name just for reference) distributed in a tree-like hierarchy (from a root WorkItem to child WorkItems).

Services are treated liked Singletons: only one instance of a Service is available during the lifetime of a specific WorkItem. Moreover, once a child WorkItem is added (to the parent’s WorkItems collection), all Services are percolated to the Service collection of the child. So, a Service registered in the root is available throughout the whole application until the root WorkItem is terminated (which will occur once the application is ended). However, Services are not static nor follow the Singleton pattern (for a quick glimpse on the Singleton pattern click here)!

The bolded and underlined line is one of the reasons that moved me to start investigating on “static” (the other one, is Factories and its implementation as Singletons, which I’ll discuss in a next post :) ). The reason for this is that each child WorkItem may override a specific Service that is passed (from its parent WorkItem) into its Service collection, so, now, we may have more than one instance of a given Service type throughout the whole application, but there still can be one and only one instance of a Service in a specific WorkItem (I think this is the scope of “Singleton Service” in CAB/SCSF). Besides, Services are not static as they can be added and removed from the WorkItem at any time.

Enough of this introduction! Let’s get into the core subject! :)

A C++ reference on “static”

The static keyword specifies that the variable has static duration (it is allocated when the program begins and deallocated when the program ends) and initializes it to 0 unless another value is specified. So, as a descriptive term it refers to the lifetime of memory or storage locations, which I’ll mention the following types:

  • static
  • dynamic (heap)
  • auto (stack)

Static storage refers to memory locations that persist for the life of the program (i.e.: global variables), while stack storage comes and goes as functions are called (the call stack composed by “stack frames” corresponding to subroutine calls), and heap storage refers to memory locations allocated and deallocated using operators new and delete.

Objects and variables defined outside all blocks have static lifetime and external linkage (its name is visible from files other than the one in which it’s defined) by default, while a global object or variable that is explicitly declared as static has internal linkage (the names of objects and functions refer only to program elements inside their own translation units, they are not shared with other translation units).

Moreover, static can also be used in terms of visibility of objects. For example:

static int _number = 2;

means that _number is not visible outside the source file it was defined. When modifying a variable or function at file scope, the static keyword specifies that the variable or function has internal linkage. However, static meaning “local to a file”  has turned obsolete with the introduction of C++ namespaces, as an unnamed namespace is used to wrap the static declarations (some more info here).

Using C++, it is possible to have static members of a class which are shared across all object instances of that class.

class MyClass {
public:
    static int _id;
    static void sharedFunction();
};

int MyClass::_id = 0;
void MyClass::sharedFunction() {}

When modifying 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 (which must be initialized at file scope).

In the example above, once the data member MyClass::_id is set to 0, that value will be shared among all object instances of MyClass. So, in recursive code, a static object or variable is guaranteed to have the same state in different instances of a block of code, which can be useful to share information between object instances.

When modifying a member function in a class declaration, the static keyword specifies that the function can be called even when a class is not instantiated. A static member function cannot be declared with the keywords virtual, const, volatile, or const volatile, and can access only the names of static members, enumerators, and nested types of the class in which it is declared (it does not have a this pointer).

In the example, the function member MyClass::sharedFunction() can be used to provide utility functions to a class. This is done when the function is related to an operation of the class but it doesn’t operate on particular object instances of the class. This is because the function doesn’t (or doesn’t need to) operate on an object’s state.

If the function’s modifier is public, it’s made global, but if it only refers to (or “has sense” inside) the class it has been defined, it’s cleaner/better to have the function as part of its package, as follows:

class MyClass {
static void sharedFunction();

public:
static int _id;
};

Now, MyClass::sharedFunction()is private (of course, it can be added to the private section of the class) to MyClass and can only be used within its member functions, instead of by the whole program.

In addition to this, a variable declared static in a function retains its state between calls to that function:

#include

using namespace std;

class MyClass {
public:
    static int _id; 
    void nonSharedFunction(int);
};

int MyClass::_id = 0;
void MyClass::nonSharedFunction(int parameter) {
    static int sharedNumber = 4;
    sharedNumber += parameter;
    cout << sharedNumber << endl;
}

int main() {
MyClass* firstInstance = new MyClass();
MyClass* secondInstance = new MyClass();

firstInstance->nonSharedFunction(2);
secondInstance->nonSharedFunction(4);

cin.get();
return 0;
}

Output:

6
10

In this example, I changed the static sharedFunction() function to a non static function called nonSharedFunction(int parameter) which accepts an integer as a parameter. The nonSharedFunction(int parameter) contains a static variable (called sharedNumber) which will be shared among all instances of MyClass, so each call to nonSharedFunction(int parameter) will increase the value of sharedNumber.

“Const” vs. “Static”

This section is to briefly distinguish that, although const means static, static does not mean const. Constants and static values are allocated in the same memory section (the static storage) as both persist for the lifetime of the program. However, static values are not constant (unless you explicitly specify so ;) ) as shown in the last example of the A C++ reference on “static” section.

Both, const and static are used to “share” values, but you use const to preserve constant a certain value (such as URIs), while the static “shared” value may vary in time (for example, a data provider).

C# “static”

C# deals with static practically in the same way as C++. The example:

public class MyClass
{
    public static int _id = 0;

    public static void sharedFunction(int parameter) {
        int number = 4;
        number += parameter;
    }
}

Means:

  • The _id data member…
    • …will be allocated when the program begins and deallocated when the program ends.
    • …will be shared by all instances of MyClass.
    • …will be publicly accessible (unless we remove the public modifier).
    • …will be initialized to 0 (unless we specify another value).
  • The sharedFunction(int parameter) function member…
    • …will be allocated when the program begins and deallocated when the program ends.
    • …will be publicly accessible (unless we remove the public modifier) by Type, not by instance.
    • …will have no this pointer.
    • …will only be able to access static data members.
    • …cannot be marked as override, virtual or abstract.

Note that, this time, the function variable sharedNumber is called just number, as we cannot declare static function variables.

Moreover, if we declare a static class, all of its members must be static as well.

Conclusion

Well, let’s get into answering the question: “When to use “static”?”. Some people have the bad tendency of using static to declare “global” values, declaring an object’s state public and static so that they can modify it from wherever they want. This is a terrible practice! This breaks the concepts of encapsulation and, therefore, visibility. It makes the code “dirty” and hard to maintain and debug.

Another “code smell” is to declare a static class with static “homeless” methods. Some people cannot find a “home” for their utility methods and tend to declare a static class to store a whole bunch of (sometimes unrelated!) methods. Some valid static classes with static methods are Factories, as they store creation methods, which do not depend on a state (although some do, for example, those ones who need some kind of configuration for all creations).

In conclusion, static must be used, for example, in data members when we want to share information among all instances of the class that contains them, and in member functions when the function doesn’t need to operate on a particular state (i.e.: creation methods; and stateless methods, but packed in a class in which they “make sense” or are related to).

References

Don’t be a "canuto"!

When I started this article, I thought it would only be a translation to English of a blog post, but then I realized that I should say why I’m translating it.

It happens to everyone that once we have learnt something, we want to show it to the rest. This applies at least to most of the things we are taught in life (if not all!). Think about for an instance: once you have learnt a valuable principle, you want to share it with others; once you have written a nice piece of code, you want to show it to everyone, test it, compare it, etc; once you have learnt to play a song, you want to play it for an audience; and so far, so on…

Well, this is the case! Angel Lopez wrote a mindset that encourages the reader to share what he knows with everyone. The original post is in Spanish (I talked to Angel about the idea of translating the post to English, and he thought it would be great! :) ), so as I won’t be a “canuto” (this term is explained in the quoted text ;) ), I’ll share what I’ve learnt and I’ll post it in English so that anybody (that speaks/reads in English, of course :P) can read it, leaving the reader without excuses for being a “canuto”! Hahahaha! :P

The translated post:

Some years ago, I realized that information and knowledge should be shared. In the environment of Informatics,this position has been promoted due to the Internet. Some time ago, we managed ourselves with BBSs and FidoNet, then mail lists, perhaps some online forum. With the appearance of blogs, accessible domains, project host systems such as SourceForge, they have made that in our profession, we could get tons of information, examples, resources, all available online.

With so much information and knowledge, one could wonder: what can I provide? Everything counts, and it seems important to me to stress this “mindset” that I try to teach in every place I visit:

Don’t be a “canuto”

Do not “encanute” information to yourself, share it. I don’t know if you are familiar with the term “canuto”, “to encanute”, outside mi country Argentina. It means keep something to oneself, without showing it, to have it or use to oneself, without sharing it. In conclusion, do not “encanute” what you know.

I even dare to leave a “Don’t be a canuto” Maturity Model:

  • Don’t be a “canuto” Level 1: share your knowledge.
  • Don’t be a “canuto” Level 2: share your knowledge and mention the sources.
  • Don’t be a “canuto” Level 3: share your knowledge, mention the sources, and publishes it in the web.
  • Don’t be a “canuto” Level 4: share your knowledge, mention the sources, and publishes it in the web, adding links to resources, other options and related subjects.
  • Don’t be a “canuto” Level 5: share your knowledge, mention the sources, and publishes it in the web, adding links to resources, other options and related subjects, and publishes a digital or paper book and provides examples.

And you, in which position do you place yourself?

We’ll be reading each other!

Angel “Java” Lopez
http://www.ajlopez.com/

Links:

Well, now, I should evaluate the article according to the “Don’t be a canuto” Maturity Model, let’s see:

  • Share your knowledge: Done.
  • Mention the sources: Done.
  • Publish it in the web: Done.
  • Add links to resources, other options and related subjects: Done.
  • Publish a digital or paper book and provides examples: Not Done (I don’t know if this applies to blog posts! :P).

Qualification: level 4. (Not bad, huh! :D)

I would like to suggest a kind of 6th level to the maturity model which would add: “writes it in several languages (programming and/or speaking)”. This could score the article with some extra points! :P

Well, I’ll wait for the official qualification once Angel reads this! :P

Cheers, Nacho!