Failed to link up following two files, when I remove the "static" keyword, then it is okay. Tested with g++.
Check with readelf for the object file, the static member seems is exported as a global object symbol... I think it should be a local object ...?
static1.cpp
class StaticClass
{
public:
void setMemberA(int m) { a = m; }
int getMemberA() const { return a; }
private:
static int a;
};
int StaticClass::a = 0;
void first()
{
StaticClass statc1;
static1.setMemberA(2);
}
static2.cpp
class StaticClass
{
public:
void setMemberA(int m) { a = m; }
int getMemberA() const { return a; }
private:
static int a;
};
int StaticClass::a = 0;
void second()
{
StaticClass statc1;
static1.setMemberA(2);
}
With error infoļ¼
/tmp/ccIdHsDm.o:(.bss+0x0): multiple
definition of `StaticClass::a'
It seems like you're trying to have local classes in each source file, with the same name. In C++ you can encapsulate local classes in an anonymous namespace:
namespace {
class StaticClass
{
public:
void setMemberA(int m) { a = m; }
int getMemberA() const { return a; }
private:
static int a;
};
int StaticClass::a = 0;
} // close namespace
void first()
{
StaticClass statc1;
static1.setMemberA(2);
}
The following is a definition of the static data member. It has to occur only in one file that's compiled and then linked.
int StaticClass::a = 0;
If you have multiple such definitions, it is as if you had multiple functions called first. They will clash and the linker will complain.
I think you are mistaking static members with static applied to namespace scope variables. At the namespace level, static gives the variable or reference internal linkage. But at the class scope level (when applied to a member), it will become a static member - one that is bound to the class instead of each object separately. That then has nothing to do with the C meaning of "static" anymore.
The statement
int StaticClass::a = 0;
actually allocates storage for the variable, this is why it should be only written once.
As for your remark, you are probably confusing two different uses of the static keyword. In C static used to mean "use internal linkage", this means that the name of a variable or function would not be seen outside the translation unit where it was defined.
In classes, static is used to define class members, that is variables or methods that don't refer to a specific instance of the class. In this case the storage for a static variable must be allocated somewhere (as it is not part of any instance), but only in one place of course.
StaticClass needs a place to store a, a static variable that will be shared by all class instances - there are two lines that do so, one in each file. Removing one will fix the linker error.
Related
#include <iostream>
class Test {
public:
static int numelem;
Test() {}
~Test() {}
int increment();
};
int Test::numelem = 0;
int Test::increment()
{
return ++Test::numelem;
}
So I want to make a counter for my Stacks data structure.
Whenever I push, it increments and when popped it decrements.
My code works, but int Test::numelem = 0; is a global variable.
I tried using inline but unfortunately I have C++14.
I only put the static int numelem instead of the whole Stack class to focus on one feature.
Is there an alternative way I can put int Test::numelem = 0; inside the class without getting any error?
This is the typical workaround. It's particularly useful for templates.
class Test {
public:
static int& numelem() {
static int val = 0; // or your initializer here
return val;
}
int increment() {
return ++numelem();
}
};
Of course, now you're accessing it with the syntax Test::numelem() instead of just Test::numelem. But something like ++Test::numelem() still works just fine.
but int Test::numelem = 0; is a global variable.
Technically, it is not a global variable but a class static member. Functionally they behave very similarly.
Is there an alternative way I can put int Test::numelem = 0; inside the class without getting any error? unfortunately I have C++14.
With C++14 the out-of-class definition for a nonconst static data member should be in the same namespace scope where the class was defined(global namespace in your example). So there is no way of defining a nonconst static data member inside the class in c++14 as we can't use inline in c++14 and the only way of defining a nonconst static data member is to put a definition at namespace scope.
This can be seen from class.static.data:
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.
But with C++17 we can use inline to define a non-const static data member inside the class.
I create a basic IBasic interface with a static field
class IBasic
{
public:
IBasic();
virtual ~IBasic();
static std::vector< std::vector<char> > Field;
};
from which the Inherit class is inherited:
class Inherit : public IBasic
{
public:
Inherit(int);
~Inherit();
void Foo();
};
The Inherit class makes some manipulations with Field static member in constructor/or member function.
In order to create an instance of the Inherit class, we need to explicitly declare a static field in the main.cpp before the main function:
#include "Basic.h"
#include "Inherit.h"
std::vector< std::vector<char> > IBasic::Field;
int main()
{
Inherit(10);
return 0;
}
The questions are:
In what namespace does the static method actually exists (global?)? Because I know that static field/function is not a class member in fact.
Is there another way to declare this static method, for example, in a
class file, inside a main function, or through creation unnamed namespace? Is it only one right variant?
How is right? What should be considered first of all?
A static member of a class is a member of its class (that's a tautology) and its class namespace (a class is a namespace). It is not a nember of any other namespace.
A non-const static data member of a class must be defined exactly once in a program, outside of any class, in the same namespace its class is defined in (a global namespace in your case). A header file is inappropriate place for such declaration. It is normally placed in an implementation .cpp file that goes together with the header file.
Having said that, an interface should not have any static data members, much less public ones. It is most likely a grave design error.
In what namespace does the static method actually exists (global?)? Because I know that static field/function is not a class member in fact.
It is declared in scope of the class. In fact the static variable is a class member, your assumption is wrong.
Is there another way to declare this static method, for example, in a class file, inside a main function, or through creation unnamed namespace? Is it only one right variant?
The usual way is to define it in the translation unit that contains the function definitions for the class.
How is right? What should be considered first of all?
There's no right or wrong way, but as mentioned definition in the same translation unit as the class function definitions is the usual way.
Here's an example usage of a static member without any inheritance.
SomeClass.h
#ifndef SOME_CLASS_H
#define SOME_CLASS_H
class SomeClass {
private:
int x;
public:
static SomeClass* const get(); // Needed For Using class to get this pointer
SomeClass();
int getX() const { return x; }
void setX( int val ) { x = val; }
};
#endif // SOME_CLASS_H
SomeClass.cpp
#include "SomeClass.h"
static SomeClass* s_pSomeClass = nullptr;
SomeClass::SomeClass() {
s_pSomeClass = this;
}
SomeClass* const SomeClass::get() {
if ( nullptr == s_pSomeClass ) {
// throw exception
}
return s_pSomeClass;
}
Another class using above class as a static member
OtherClass.h
#ifndef OTHER_CLASS_H
#define OTHER_CLASS_H
class SomeClass; // Forward Declaration
class OtherClass {
private:
static SomeClass* pSomeClass; // The Static Member to this class
int y;
public:
OtherClass();
int getY() const { return y; }
void setY( int val ) { y = val; }
void useSomeClassToSetY();
};
#endif // OTHER_CLASS_H
OtherClass.cpp
#include "OtherClass.h"
#include "SomeClass.h"
SomeClass* OtherClass::pSomeClass = nullptr;
OtherClass::OtherClass() {
if ( nullptr == pSomeClass ) {
pSomeClass = SomeClass::get();
}
}
void OtherClass::useSomeClassToSetY() {
// First Set X To Some Value:
pSomeClass->setX( 10 ); // Use of Static Member
y = pSomeClass->getX(); // Use of Static Member
}
Static members still belong to the class, but they have static storage.
I want to only have 2 extern C functions, which are how to interact with the API. Then inside the static .lib I want to have my class that does all the work. But it shouldnt be visible to the outside.
I can do it with just pure C functions by declaring them static inside a compilation unit, but how do I do it with a class ?
If I understand your question well:
you want to create a static library presenting only two functions to the outside world
but the internals of this library should be based on a class you want to hide from outside world.
you know how to do hiding internals in classic c (i.e. using auxiliary static functions and static variables) but you don't see how to do with classes
If this is the case, the trick is simply to use an unamed namespace:
In your library source you would have something like this:
namespace { // anonymous
class U { // class visible only to the library
public:
int y;
U() :y(0) { cout << "U\n"; }
void mrun() { y++; }
};
}
void f() {
U x;
...
}
You may then use your library from outsilde world:
extern void f(); // declare the function (in a header)
f(); // invoke the function
Even if the auxiliary class would be declared in the outside world:
class U { public: int y; U(); void mrun(); };
It would not be able to used and linking errors would be generated if it would be tempted to use U. This is because unnamed namespaces are unique to each compilation unit.
If you use the same kind of solution but without the anonymous namespace, the auxiliary class would be visible and the link would succeed.
Perhaps you could mirror the class's API using C functions a bit like this:
class Cpp
{
int i = 0;
public:
int get_i() { return i; }
void set_i(int i) { this->i = i; }
};
// C code has a void* as a handle to access
// the correct instance of CPP
extern "C" void* new_Cpp()
{
return new Cpp;
}
extern "C" void delete_Cpp(void* cpp)
{
delete reinterpret_cast<Cpp*>(cpp);
}
extern "C" int Cpp_get_i(void* cpp)
{
return reinterpret_cast<Cpp*>(cpp)->get_i();
}
extern "C" void Cpp_set_i(void* cpp, int i)
{
return reinterpret_cast<Cpp*>(cpp)->set_i(i);
}
When a static member variable is declared private in a class, how can it be defined?
Suppose i have the following class declaration
class static_demo
{
private:
static int a;
public:
static int b;
void set(int x, int y)
{
a = x;
b = y;
}
void show()
{
cout << "a = " << a << "\n";
cout << "b = " << b << "\n";
}
};
Then the following statement to define a will result in compilation error.
int static_demo::a;
So is it possible to have a static data member in the private section of class?
Adding full code as per Greg,
#include <iostream>
using namespace std;
class static_demo
{
private:
static int a;
public:
static int b;
void set(int x, int y)
{
a = x;
b = y;
}
};
int static_demo::a;
int static_demo::b;
int main()
{
static_demo::b = 10;
static_demo::a = 20;
return 0;
}
The compilation error is:
static_member_variable.cpp: In function `int main()':
static_member_variable.cpp:20: error: `int static_demo::a' is private
static_member_variable.cpp:26: error: within this context
When a static member variable is declared private in a class, how can it be defined?
In the very same way as you define a public static variable in your source(cpp) file.
int static_demo::a = 1;
Access specifiers will not give you error while defining the member. Access specifiers control the access of the member variables, defining a static variable is an excpetion which is allowed.
Compiles cleanly on Ideone here.
EDIT: To answer your Q after you posted code.
Your problem is not the definition of the static member. The error is because you are trying to access the private static member inside main. You cannot do that.
Private members of a class can only be accessed inside the class member functions, the same rule applies even to static members. To be able to modify/access your static members you will have to add a member function to your class and then modify/access the static member inside it.
in your .cpp:
int static_demo::a(0);
when this causes an error, it is most common that you either encountered a linker error for a multiply defined symbol (e.g. the definition was in the header), or that you may have tried to define it in the wrong scope. that is, if static_demo is in the namespace MON, it would be defined in the .cpp:
#include "static_demo.hpp"
int MON::static_demo::a(0);
for other types, it may simply have been an incorrect constructor.
The problem is not the definition, but the fact that in main() (that's not in the name scope of static_demo, and cannot see a being private), you do an assignment.
The definition of a is what you did at global scope, with int static_demo::a;.
You simply need an initializer, if you want a not to start with an undefined value.
int static_demo::a = 1;
will solve the problem.
From than on, a can be manipulated only by functions in static_demo (of friend of it).
I would like to have a static member variable keep track of the amount of objects that have been made. Like so:
class test{
static int count = 0;
public:
test(){
count++;
}
}
That doesn't work because, according to VC++, a member with an in-class initializer must be constant. So I looked around and apparently you're supposed to do:
test::count = 0;
Which would be great, but I want count to be private.
edit:
Oh boy, I just realized I need to do:
int test::count = 0;
I had seen something just do test::count = 0, so I assumed you wouldn't have to declare type again.
I'd like to know if there's a way to do this inside the class though.
edit2:
What I'm using:
class test{
private:
static int count;
public:
int getCount(){
return count;
}
test(){
count++;
}
}
int test::count=0;
Now it's saying: 'test' followed by 'int' is illegal (did you forget a ';'?)
edit3:
Yup, forgot a semicolon after the class definition. I'm not used to having to do that.
Put
static int count;
In your header in the class definition, and
int test::count = 0;
In the .cpp file. It will still be private (if you leave the declaration in the header in the private section of the class).
The reason you need this is because static int count is a variable declaration, but you need the definition in a single source file so that the linker knows what memory location you're referring to when you use the name test::count.
Initialization of static variable within a function is allowed so a solution can be something like this
class test
{
private:
static int & getCount ()
{
static int theCount = 0;
return theCount;
}
public:
int totalCount ()
{
return getCount ();
}
test()
{
getCount () ++;
}
};
in general using this technique it is possible to work around the C++ limitation regarding static member initialization in the declaration.
static class members must be defined (and potentially initialized) at namespace scope, member access rules do not apply.