Sorry if this question seems trivial to many here.
In a C++ code there is something as below:
class Foo
{
public:
static int bands;
...
...
private:
...
...
}//class definition ends
int Foo::bands; //Note: here its not initialized to any value!
Why is the above statement needed again when 'bands' is once declared inside the class as static?
Also can a static variable be declared as a private member variable in any class?
C++ notes a distinction between declaring and defining. bands is declared within the class, but not defined.
A non-static data member would be defined when you define an object of that type, but since a static member is not a part of any one specific object, it needs it's own definition.
a) It's needed because that's the way the languge is designed.
b) Static variables are initialized by their default constructor, or to zero for built-in types.
c) Yes, they can be (and usually are) private.
Take a look at this question.
It has to do with obj files, how they are used, and how memory addresses for globally scoped variables are ultimately discovered through the linking process. Object files contain the addresses of all global data and functions defined in the corresponding cpp. They layout some memory in a relative fashion to tell the liker where in that file these global vars/funcs can be found. So for example
function doFoo can be found 0 bytes from beginning of this file
int foo::bands can be found 12 bytes from beginning of this file
etc
Its almost easier to think about if you've done straight C before. In a pure C world you would do things in a more traditional modular programming sense. Your module would be defined with a header and a cpp. The header would define a "public" variable like below, using the extern keyword, then instantiate it in the cpp.
foo.h
extern int bands;
foo.cpp
#include "foo.h"
int bands;
foo.obj:
int bands can be found 0 bytes from the beginning of this file
The "extern" keyword states that this name is valid and its address will get resolved at link time. Everyone that included "foo.h" and wanted to use the "bands" global variable had could now use it. At link time, the linker would figure out that bands existed in the foo.obj. If you forgot to put "int bands" in foo.obj, you'd get a linker error, and have to go resolve it.
In C++ using static in a class declaration i similar. You are telling the users that there exists this thing called "foo::bands" and where it will live will get resolved at link time. Later down the line, the linker sees that in foo.obj, foo::bands exists, and all references to foo::bands can be resolved.
My understanding is that you would only need to declare Foo::bands if you planned on using it prior to ever creating an instance of your class. Basically, when you declare a static in a C++ class then only one copy of that variable exists for all instances of that class. However, you can't normally access Foo::bands until an instance of the class is declared.
For example:
Pointers to Members
#include <iostream>
using namespace std;
class X {
public:
int a;
void f(int b) {
cout << "The value of b is "<< b << endl;
}
};
int main() {
// declare pointer to data member
int X::*ptiptr = &X::a;
// declare a pointer to member function
void (X::* ptfptr) (int) = &X::f;
// create an object of class type X
X xobject;
// initialize data member
xobject.*ptiptr = 10;
cout << "The value of a is " << xobject.*ptiptr << endl;
// call member function
(xobject.*ptfptr) (20);
}
Related
When I create a function, I can put the code for it after main if I put the prototype above main. For example,
int myFunction(int a)
{
return(a);
}
would have the prototype..
int myFunction(int a);
above main.
However, I have not been able to get this to work for a class definition.
If I put …
class myClass
{
…
};
below main,
I get an error if I put
class myClass;
above main. The error occurs where the class is used within main, and the error is "unknown type name." That's with the c++ compiler that is part of Xcode.
What kind of prototype should I enter above main if the class definition is below main?
When you call a function and the definition is not available, the compiler doesn't have to know the contents in order to continue evaluating the rest of the code (eg: stack usage at the call site). It only needs to know the function's signature to ensure the correct parameters are going to be passed into the function. The linker will hook up the actual address for the function call after the compiler is done.
However when you are using a class it has to know about the details of it - not just that it exists - because it'll need to ensure proper layout on the stack, what parameters are required for the constructor, etc.
The details of the class' functions are of course like regular functions - it just needs the signature to work with - they can be defined later.
A function in C++ is like a black box to its callers; they just need to know what to pass it and what it returns in order to use it.
Classes, on the other hand, cannot be used in this way, because the compiler needs to know how much space to allocate for them, what the types of their members are, etc.
A class definition is a little different because it can contain member function prototypes and definitions.
If your class definition (usually placed in a .h file) is in the same file, then you'll want it to be above your main(). Functions defined outside of your class definition can be defined after main() as shown below.
class Foo
{
// member function prototype
void func1();
//member function definition inside class
void func2()
{
std::cout << "Hello from func2" << std::endl;
}
};
int main()
{
foo instance;
instance.func1();
instance.func2();
return 1;
}
void Foo::func1()
{
std::cout << "Hello from func1" << std::endl;
}
In a way, a function prototype is the function-equivalent of a complete class definition, not a forward declaration.
so, forward declaration:
class X;
introduces the name X and informs the compiler that it is a class. After seeing this, the compiler will allow you to hold and transfer references and pointers to an X, but not create or copy values (instances) of it, so:
void foo(X&); // is allowed (because it deals in references), but
void foo(X); // is not (it deals in copies of an X)
class definition:
class X { ... };
fully defines X's interface and storage requirements. After this, the compiler will allow you to do anything you like with an X. This is why the class definition generally goes into a header file.
function prototype involving forward-declared classes:
int foo(X&); // X may be forward-declared or defined
This has fully declared the complete shape and behaviour of calling foo(X&). The code at the call-site can be completely compiled.
function prototype involving defined classes:
int foo2(X); // X must be defined
This has fully declared the complete shape and behaviour of calling foo2(X), including the requirements for copying the X onto the stack (for emplacing it there when called with a temporary). The code at the call-site can be completely compiled.
In C and C++ all static variables are initialized by default to ZERO.
This is not the case of static class data members. Why is that?
#include <iostream>
using namespace std;
int var;
class MyClass
{
public:
static int classVar;
};
int MyClass::classVar = 0; // Why I have to init it here?
int main(void)
{
cout << ::var << endl; // this is initalized to ZERO by default
static int var;
cout << var << endl; // and this also is initalized to Zero
cout << MyClass::classVar << endl;
return 0;
}
At class scope,
int MyClass::classVar = 0; // Why I have to init it here?
is a definition and
static int classVar;
is a declaration, ie. a promise the variable will be defined somewhere: you must define exactly once the variables you declare.
The rationale is that the class declaration will likely be included in multiple source files. Would a part of it be a definition, it would take place multiply: this is erroneous (exceptions are inline [member] functions).
Note that according to value initialization rules, you can get along with
int MyClass::classVar; // Zero-initialized !
as a definition.
Variables declared at namespace scope are definitions too (unless they are extern qualified):
int var;
is a declaration, and a definition: if you put this into a header and include it in multiple translation units, you have an error ("multiply defined symbol", or something along those lines).
[Note that in C++ (and not in C), if the var above is const, it becomes automatically static and there is no violation of the One Definition Rule should it be put into a multiply included header. This goes slightly off topic, but feel free to ask details]
C++ FAQ 10.12 states that:
static data members must be explicitly defined in exactly one compilation unit.
From C++ FAQ http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12
Does that answer your question or were you after a reference to the C++ standard itself?
You have to initialize your static class data variables, because you have to tell the compiler what their value is. Classes need not have a notion of a default value.
Variables types have a logical "zero value", for int it is 0, for double 0.0, for a string "" etc. In contrast, classes do not necessarily have a default value. Consider, for example class Rectangle. What is its zero value - a rectangle with zero square or a rectangle with unit side length? For static variables, a compiler asks you to define yourself, what value your static variable must have, because not every data type can be initialized by a default value.
My question: What exactly is the out of class definition of k doing under the hood to make sure it's address is available?
#include <iostream>
using namespace std;
class A {
public:
static const float k = 7.7;
};
//const float A::k; --> without this line compiler error
int main()
{
cout << &A::k;
}
The class "definition" is actually only providing a "declaration" of A::k. Yeah, I know it's confusing, but the idea is to allow the class definition to be in a .h (included from multiple .cpp sources) without creating ambiguities: one, and only one, of those .cpp sources, must provide the actual definition to match A::k's declaration (the latter being part of class A's definition).
Other answers have already given the how to fix it -- I'll go more into the why.
When you do this:
#include <iostream>
using namespace std;
class A {
public:
static const float k = 7.7;
};
int main()
{
cout << A::k;
}
The compiler is probably in reality generating this:
#include <iostream>
using namespace std;
class A {
public:
static const float k = 7.7;
};
int main()
{
cout << 7.7;
}
which means there will be no link-time dependency between this translation unit and A::f -- the compiled code doesn't reference A::f at all!
However, when you use &A::f, you force the compiler to generate an address for A::f. Therefore that translation unit does have a dependence on A::f. Since you have not defined it, you get a linker error, because the linker cannot find an address for it. For the address to exist, A::f must be defined in one and only one translation unit. To choose the translation unit in which it should reside, you need to define it there.
You also have an invalid code issue with your class above though -- only static const integral members may be initialized with the syntax you've used (putting k = 7.7 in the class body) -- float is not an integral type.
It sounds like you're wondering why the variable needs to be defined even though you aren't accessing it.
To print its address, it needs to have an address. To have an address, it must exist. To exist, it needs to have a definition and the linker needs to assign it a place in global variable space. So, there really isn't a middle ground.
"Under the hood," the definition tells the linker what the initializer for the global is. (In this case, the initializer is in the class block. But that's nonstandard. The official way is to write const float A::k = 7.7;) Without knowing that, it can't produce the executable file.
Also, unless the compiler performs impossibly detailed analysis, it can't really tell that operator << doesn't somehow pass that pointer to some other function or OS service that will access the value of k.
If you could define like static const float k = 7.7; as you wish, you will end up in multiple definitions (since static members will be defined only once), wherever you are including it.
To avoid that the definition is made reside separately in a cpp file.
From C++ standard docs sec 9.4.1,
A static data member is not part of the subobjects of a class. There is only one copy of a static data member shared
by all the objects of the class.
Also 9.4.2 states that,
The declaration of a static data member in its class definition is not a definition and may be of an incomplete type
other than cv-qualified void. The definition for a static data member shall appear in a namespace scope enclosing the
member’s class definition.
Hope it helps..
The one which is inside the class is the declaration of the variable k. You need to define it in exactly one translation unit in order to link your program correctly. Hence that statement is required.
A static variable can be deemed as data shared by all the objects of the class and hence only one copy of this variable should be created. With this said, with whom should lie the responsibility of allocationg memory for this member? Obviously it can't be object's responsibility as there could be multiple objects which would raise another challenge as to which object should allocate memory for this member.
So typically compliler expects out of class, explicit definition of this member and hence the line:
const float A::k;
This ensures that the static member variable is accessible to all the objects of the class. The memory for this variable is allocated on globally accessible memory.
This is an expansion of the scope of a previous question of mine.
What exactly is "static", how is it used, and what is the purpose of using "static" when dealing with C++?
Thanks.
It means that the variable is local to a translation unit (simply put, to a single source file), and cannot be accessed from outside it. This use of static is in fact deprecated in the current C++ Standard - instead you are supposed to use anonymous namespaces:
static int x = 0;
should be:
namespace {
int x = 0;
}
The keyword static has different meanings in C++, depending on the context.
When declaring a free function or a global variable it means that the function is not to be available outside of this single translation unit:
// test.cpp
static int a = 1;
static void foo() {}
If the result of compiling that translation unit is linked with a different translation unit containing symbols a and foo it will not break the One Definition Rule, as in this particular translation unit a and foo are private symbols. This use has been obsoleted by unnamed namespaces.
// test2.cpp
namespace {
static int a = 1;
static void foo() {}
}
When declaring a local variable within a function it means that the lifetime of the variable will extend from the first call to the function to the end of the program, and not only for the duration of the call:
int foo() {
static int counter = 0;
return ++counter;
}
int main() {
for ( int i = 0; i < 10; ++i ) {
std::cout << foo() << std::endl;
}
}
In the previous code, counter is initialized once when foo is called for the first time, but the variable will outlive the function and keep the value across different function calls. The previous code will print "1 2 3 4... 10". If the variable was not declared static then the output would be "1 1 1... 1".
Within a class scope, static means that the member is a member of the class, and not of a particular instance. This use is equivalent to the use in your other question: usage of that particular member is not bound to any specific object.
struct test {
int x;
static int y;
};
int test::y; // need to define it in one translation unit
int main() {
// test::x = 5; // !error cannot access a non-static member variable
// without an instance
test::y = 5; // ok
test t, other;
t.x = 10; // ok
t.y = 15; // ok, the standard allows calling a static member through
// an instance, but this is the same as test::y
}
In this case, the member x is a non-static member attribute, and as such there is a different x for each instance of the class. In the sample program t.x and other.x refer to different integers. On the other hand y is static and thus there is a single instance of test::y in the program. Even if the standard allows to call t.y and other.y both uses refer to the same variable. The same goes with member methods. If they are static they are class-level methods and can be called without an instance, while if they are non-static they are applied to a concrete instance and the a.b or a->b syntax must be used.
This use of static is similar to the use of the same keyword in Java, while the other two are not present in that language. There is one use of the keyword in Java that is not present in C++, and that is the use of static class initializers (a block of code at class level surrounded by static { ... }). In Java that block of code will be executed when the class is loaded and only once. Initialization of static member variables in C++ must be done in the initializer of the variable definition.
This stuff seems to be fairly well covered here.
But to paraphrase, there are 2 uses in C
Prevent the use of a global variable outside the scope of the file that defines it.
Allow local variables within a function to persist accross invocations of the function, as in
int getNextId()
{
static int id = 0;
return id++;
}
C++ inherits both of these, and adds two uses of its own.
static member variables: Variables that are "shared" accross all instances of a class, and can also be accesses without reference to an instance of the class. Shared seems like the wrong word, but in essence I beleive that the result is that any reference to a static member variable references the same memory location.
static methods: Methods that can be called without reference to a specific instance of the class that defines it.
Static basically means that a variable is tied to the lifetime of the program and not of any given function or class instance. When should you use it? Don't. What is the purpose? Debugging data, mostly.
Generally, in C++, if you find yourself using static data, you've done it wrong. There are times when it's appropriate, but they're very rare.
When static is used in a class in C++, it means more or less the same thing that it does in Java. For variables it means that one one instance of the variable exists for all classes and for functions, it means that the function does not implicitly access the this pointer at all.
In C and C++ when static is used for a global variable or function, then it means that the variable may only be referenced in the current C or C++ file. In other words, the compiler must not generate any relocation symbols for the variable or function.
When static is used next to a variable in a local function, it means that the variable does not go out of scope but will retain its value from function-call to function-call. The variable become effectively a global variable that can only be accessed from the given function.
Static class members are data and functions that are associated with the class itself, rather than with the objects of the class.
In the following example, class Fred has a static data member x_ and an instance data member y_. There is only one copy of Fred::x_ regardless of how many Fred objects are created (including no Fred objects), but there is one y_ per Fred object. Thus x_ is said to be associated with the class and y_ is said to be associated with an individual object of the class. Similarly class Fred has a static member function f() and an instance member function g().
class Fred {
public:
static void f() throw(); <-- 1
void g() throw(); <-- 2
protected:
static int x_; <-- 3
int y_; <-- 4
};
(1) Member function associated with the class
(2) Member function associated with an individual object of the class
(3) Data member associated with the class
(4) Data member associated with an individual object of the class
Usage:
When you want to keep tract of the number of instances of a class created you use static variable. For example in a 'Car' class each Car instance may have a unique serial number(_y in this case) and the company may want to keep track of the number of cars produced(_x in this case).
I have a few questions about the static keyword in C++ (and probably with other languages as well.) What is the purpose of declaring a function as static?
void static foo(int aNumber) {
... }
How about a static inline function?
void static inline foo(int aNumber) {
... }
Is there any benefit to using the static keyword with a function, and do those benefits apply to class functions as well?
I realize some datatypes like structs and arrays have to be static when compiling with an older compiler, but is there any point when using a new ANSI-C++ compiler (like MS VC++ 2008)? I know that using a static variable inside a loop saves time by keeping the data in memory and not reallocating memory every loop iteration, but how about when a variable is declared only once, like at the top of a header file or within a namespace?
Depends on Context:
Like many things in C++, static means different things depending on its context.
It's very common in C++ for the same word to mean different things depending on its context.
For example:
* is used for multiplication, dereferencing a pointer, and creating pointers.
& is used to get the address of variables, to declare a reference, and as a bitwise AND operator.
Global use of static:
If you declare a function or variable as static outside of a class and in global scope, it is specific to only that file. If you try to use that variable or function in a different file (via a forward declaration) you will get a linking error.
Example:
a.cpp:
static void fn()
{
cout<<"hello a!"<<endl;
}
b.cpp:
void fn();
void gn()
{
fn();//causes linking error
}
This feature allows you to use a function that no other file will ever see, that way you don't cause possible linker errors of a symbol defined multiple times. The preferred method to do this is with anonymous namespaces though:
a.cpp:
namespace
{
void fn() // will be static to a.cpp
{
cout<<"hello a!"<<endl;
}
}
Inside of a class use of static:
If you declare a function or variable as static inside of a class (or struct), it is a class function or class variable. This means that there is only one for that whole class. A class function can only use class variables. A class variable is shared amongst all instances of that class.
class C
{
public:
static void fn()
{
y = 4;//<--- compiling error
// can't access member variable within a static function.
}
int y;
}
This is a great feature to use if you have something that is specific to the class of your objects, but not specific to an instance.
Inside a function use of static:
If you declare a variable as static inside of a function, you can consider that the variable value will persist upon calls. It will only be initialized once.
Example:
//Will print 0, then 1, then 2, ...
void persistentPrintX()
{
static int x = 0;
cout << x << endl;
x++;
}
I personally try to avoid this, and you probably should to. It is not good to have global state. It is better to have functions that given the same input guarantees the same output.
Just like in the English language:
The concept of context sensitive meaning is not specific to C++, you can even see it in the English language.
I am going to screen a movie (Means showing the movie)
The screen on the TV is broken (Means a part of the TV)
Other meanings in other programming languages:
Depending on the programming language there can be a different meaning, but the first thing most people think of when you say static is a class variable/function vs a member variable/function.
I hang around on the ##c++ irc channel on irc.freenode.net and I really like the clarification on static that the bot nolyc is programmed to give. I quote word for word:
When used inside a function, the
static keyword indicates that a
variable is shared between all calls
of the function. When used inside a
class, it indicates that the variable
or function is a member but is not
tied to a specific instance. When
used inside a namespace, it specifies
internal linkage.
I hope that clears things up. I haven't answered all your questions. I would say that you should use the static keyword to do what it was intended to do. Use it as a tool to accompolish your task, if it is the right one for the job. As far as benefits go, I wouldn't worry. If you need to optimize, then think about those effects if there is no other resort.
I hope this helps.