The following code is throwing an error message and I can't figure out what the issue is - is it the word static, or const? What am I doing wrong?
#include <iostream>
using namespace std;
class SampleClass
{
private:
int value;
static int counter;
public:
SampleClass(int i)
{
value = i;
counter++;
}
static int countSomeClass() const
{
return counter;
}
void showValue()
{
cout << value << endl;
}
};
int main()
{
SampleClass test(50);
test.showValue();
test.countSomeClass();
return 0;
}
Error message:
main.cpp:16:35: error: static member function static int SampleClass::countSomeClass() cannot have cv-qualifier
static int countSomeClass() const
A static method cannot be marked as const: since it doesn't work on an instance, it makes no sense to specify that it cannot modify it.
(you could argue that for static methods it could have referred to static methods that cannot modify the static data associated with the class; however, this would have no use anyway, since you cannot have a const class or form a const pointer or reference to a class, as in C++ classes aren't objects)
As the error message says, a static member function can't have a cv-qualifier - that is, a const or volatile qualifier. Such qualifiers are applied to this within a non-static member; they make no sense on a static member which has no this.
You want the function to be static, since it doesn't depend on any instance; so remove the const.
A static function cannot be const (cv-qualified) and vice-versa. It is the combination of the two that is the problem.
From the C++ specification § 9.4.1/2 (emphasis mine)
[ Note: A static member function does not have a this pointer (9.3.2). —end note ] A static member function shall not be virtual. There shall not be a static and a non-static member function with the same name and the same parameter types (13.1). A static member function shall not be declared const, volatile, or const volatile.
A static function has no this access since it is not associated with a specific instance of an object. There is no need for a const to be applied, it wouldn't make sense - there is no instance of an object to apply the const to. In a similar way, a free function cannot be const (or cv-qualified).
If you wish the function to be associated with an object, remove the static, if you want it to be static remove the const - from your sample, remove the const.
One more note; your counter is declared but not defined (outside the class). It requires something like int SampleClass::counter = 0; in one of the translation units (cpp file).
It's related to both.
A static member function does not work on an instance of the class it's a member of.
The const keyword at the end of a member function signature indicates that this member function does not modify the instance it's called on.
So it makes no sense (and is thus invalid) to have both in the same member function declaration.
Related
I'm new to C++, and I just can't understand that why I can't assign a value to a non-const static member inside a class (like we do in java static int x = 12; ) even thought I can
declare a non-const static member (static int x;)
declare a static const member (static const x;)
assign a static const member (static const int x = 12;)
note: my class and my main() function are in the same file
In general
A static variable inside a class, just like everything else, is just a declaration by default. C++ then requires you to provide a single definition per entity that requires one, that's the One Definition Rule. The definition is where the initializer (which is not an assignment, but a construction) goes, since there should be only one as well. It is typically placed in a .cpp file so that it can't be accidentally duplicated by #includes.
The constant case
When a static member is a constant integer or enumeration, and is initialized with a compile-time expression, the initializer is allowed to be placed on the declaration, and the definition skipped. This is a result of a combination of old rules and isn't really interesting today IMO.
Proper inline initialization
Since C++17 introduced inline variables, you can use them as static members. The rules are roughly the same as inline functions, and are pretty sensible: you can provide multiple definition of an inline entity, you are responsible for ensuring that they are all strictly identical, and the implementation is responsible for collapsing them into a single definition with its initializer. Thus, what you're looking for is written:
struct Foo {
static inline int bar = 42;
// ^^^^^^
};
You have to initialise the static member outside the class definition like in this example:
class Box {
public:
static int x;
};
// Initialize static member of class Box outside the class definition
int Box::x = 12;
int main(void) {
...
}
Why I can write this:
class VoiceManager
{
public:
static const int mMaxNumOfVoices = 16;
Voice mVoices[mMaxNumOfVoices];
private:
};
but I can't use this:
class VoiceManager
{
public:
const int mMaxNumOfVoices = 16;
Voice mVoices[mMaxNumOfVoices];
private:
};
It says: "a nonstatic member reference must be relative to a specific object"
But in both case, mMaxNumOfVoices is a const and will be init before mVoices init (compiler follow the declaration order, no?).
But it requires static. Why?
Array bounds must be known at compile-time. Though your initialisation is written there in the code, it can be overridden at runtime by a constructor. Hence your non-static member variable is not a compile-time constant.
The const keyword means read-only, not constant, is like a not-be-changed promise for a specific part of the program. If you have a pointer-to-const then other parts of the program may change the value while you're not looking.
But a static const is guaranteed that remains unchanged for the rest of the program. The storage for the object is allocated when the program begins and deallocated when the program ends. Only one instance of the object exists. All objects declared at namespace scope (including global namespace) have this storage duration.
I have a question about static and static const variable in class.
Especially curious about the memory status about static and static const.
In the following code,
#include <iostream>
using namespace std;
class test{
public:
static const int testConstStatic =1;
static int testStatic;
};
int test::testStatic = 0;
int main(){
cout << test::testStatic << endl;
cout << test::testConstStatic << endl;
return 0;
}
why does 'static int testStatic' need definition to be used and if not, I got 'undefined reference' about testStatic?
Does this definition make linkage about testStatic?
And what about testConstStatic?
Thanks in advance!
UPDATED!!
The main reason of this question was that when I declared static variable as global which surely not defined and printout then no message about 'undefined reference' BUT for the static variable in CLASS without definitino it show the message 'undefined reference'
#include <iostream>
using namespace std;
static int testStaticInGlobal;
class test{
public:
static int testStatic;
};
int test::testStatic = 0;
int main(){
cout << test::testStatic << endl; // 'Undefined reference' error without definition
cout << testStaticInGlobal << endl; // no error without definition
return 0;
}
Thanks!
All variables in C++ must be defined before use. How this definition occurs is dependent on the type of variable.
For non-static class member variables, the definition may be implicitly performed by the class's constructor (which may itself be implicit).
Since static variables, by definition, are not intialized by a constructor, static member variables must always have an explicit definition.
For convenience, C++ allows the definition of a static const member to be combined with its declaration, as you have done, under certain circumstances. Conceptually, the static const int testConstStatic = 1; is doing two distinct things: declaring the testConstStatic member, and defining it to have a value of 1. For whatever reason, the language designers did not choose to allow these two steps to be combined for non-const static members.
Incidentally (to address Ed Heal's comment), a non-static const member (like any non-static member variable) must be defined at construction of object; it will not change after construction is completed, but it may have a different value for each instance of the class, unlike a static const member, which will always have one and only one value for the entire duration of the program.
static const int members are a special case. They're treated as compile-time constants in most usage, and thus a storage location for them isn't required. The only exception is when you try to make a pointer or reference to this variable, then it needs a place to live and you'll need to provide a definition.
static member variable needs to be defined outside the class. That's a rule.
C++11 onwards, const static members usually don't have to be defined outside the class.
Static data members are treated as global variables shared among the object instances, so they ned to be defined once only, and safe bet is outside the class.
const variables are by definition static. So the static in static const is redundant. i.e. just const will do.
The static is required for the static int because without it, the variable is a normal non-static member variable that is only defined for the instance.
What is the reasoning to why static const members cannot exist in local classes? It seems like a rather silly restriction.
Example:
void foo() {
struct bar {
int baz() { return 0; } // allowed
static const int qux = 0; // not allowed?!?
};
}
struct non_local_bar {
int baz() { return 0; } // allowed
static const int qux = 0; // allowed
};
Quote from standard (9.8.4):
A local class shall not have static data members.
From the standard section 9.4.2:
If a static data member is of const integral or const enumeration
type, its declaration in the class definition can specify a
constant-initializer which shall be an integral constant expression.
In that case, the member can appear in integral constant expressions
within its scope. The member shall still be defined in a namespace
scope if it is used in the program and the namespace scope definition
shall not contain an initializer.
Basically, local classes have no linkage, and static data members require a linkage.
Since there's no way to define a static data member of a local class in namespace scope (a declaration with an initializer is not a definition), they are not allowed, whether they are of const integral type or not. On the surface it may seem like the compiler should just be able to inline the value, but then what happens if you try to access a pointer to the member? With namespace scoped classes you'd just get a linker error, but local classes have no linkage.
I guess in theory they could just allow you to use static const integral types in local classes as long as they are only used in integral constant expressions, but it would probably just put too much of a burden on the standards body and compiler vendors to differentiate for very little practical value; local static variables are accessible from local classes, so using a local static const should be just as good.
I dont think there is a.reason. Normal static datamembers are disallowed because there is no way to define them after being declared.
Also dont forget you can create a local const variable outside the.class that you can use inside the class as long as you only read its value (that is, as long as you dont take.its.address).
Static members of a class need to be defined in global scope, e.g.
abc.h
class myClass {
static int number;
};
abc.cpp
int myClass::number = 314;
Now, since the scope inside void abc(int x) is not global, there is no scope to define the static member.
As things progress, we now have C++11 and with that you can define integral constants variable members in your classes.
class test
{
public:
const int FOO = 123;
[...snip...]
};
That works when you compile with C++11. Notice that the static keyword is not used. When compiling with optimizations turned on, those variables will likely all get optimized out. In debug, though, they appear in your structure as regular variable members.
Note, however, that the size of the class/structure will still include that variable. So here it is likely 4 bytes for the variable FOO.
However, in most cases, classes defined in a function will completely be optimized out so this is a great way of doing things (a good 50% of my classes have such variable members!)
What is the reasoning to why static const members cannot exist in local classes? It seems like a rather silly restriction.
Example:
void foo() {
struct bar {
int baz() { return 0; } // allowed
static const int qux = 0; // not allowed?!?
};
}
struct non_local_bar {
int baz() { return 0; } // allowed
static const int qux = 0; // allowed
};
Quote from standard (9.8.4):
A local class shall not have static data members.
From the standard section 9.4.2:
If a static data member is of const integral or const enumeration
type, its declaration in the class definition can specify a
constant-initializer which shall be an integral constant expression.
In that case, the member can appear in integral constant expressions
within its scope. The member shall still be defined in a namespace
scope if it is used in the program and the namespace scope definition
shall not contain an initializer.
Basically, local classes have no linkage, and static data members require a linkage.
Since there's no way to define a static data member of a local class in namespace scope (a declaration with an initializer is not a definition), they are not allowed, whether they are of const integral type or not. On the surface it may seem like the compiler should just be able to inline the value, but then what happens if you try to access a pointer to the member? With namespace scoped classes you'd just get a linker error, but local classes have no linkage.
I guess in theory they could just allow you to use static const integral types in local classes as long as they are only used in integral constant expressions, but it would probably just put too much of a burden on the standards body and compiler vendors to differentiate for very little practical value; local static variables are accessible from local classes, so using a local static const should be just as good.
I dont think there is a.reason. Normal static datamembers are disallowed because there is no way to define them after being declared.
Also dont forget you can create a local const variable outside the.class that you can use inside the class as long as you only read its value (that is, as long as you dont take.its.address).
Static members of a class need to be defined in global scope, e.g.
abc.h
class myClass {
static int number;
};
abc.cpp
int myClass::number = 314;
Now, since the scope inside void abc(int x) is not global, there is no scope to define the static member.
As things progress, we now have C++11 and with that you can define integral constants variable members in your classes.
class test
{
public:
const int FOO = 123;
[...snip...]
};
That works when you compile with C++11. Notice that the static keyword is not used. When compiling with optimizations turned on, those variables will likely all get optimized out. In debug, though, they appear in your structure as regular variable members.
Note, however, that the size of the class/structure will still include that variable. So here it is likely 4 bytes for the variable FOO.
However, in most cases, classes defined in a function will completely be optimized out so this is a great way of doing things (a good 50% of my classes have such variable members!)