c++ static class variable without cpp file - c++

I have a simple class for storing sensor data which can be summarized as
class Data
{
public:
Data(){timestamp = Time::now(); id = sNextID++; data = 0; type = DATA_TYPE_UNKNOWN;}
double data;
Time timestamp;
DataType type;
private:
static unsigned int sNextID;
};
I have a header file that declares a bunch of similar data classes. Given the simplicity of the classes there is no need for an implementation cpp file.
The problem is, without an implementation file how do I initialize sNextID? I read somewhere that it defaults to 0 which would be fine, although relying on that seems a bit hackish. More importantly, though, without initializing it somewhere the linker complains of an undefined reference.

Use inline function (free-standing or member):
inline unsigned &sNextID()
{
static unsigned data = 0;
return data;
}
Or class template (defenition of it's statics can be in header file):
template<typename tag>
struct Foo
{
static unsigned sNextID;
};
template<typename tag>
unsigned Foo<tag>::sNextID=0;
Update: In C++17 inline variables are available:
struct Foo
{
static inline unsigned sNextID;
};

in the header file (let's say it's name is data.h), add this at the end
class Data
{
.....
private:
static unsigned int sNextID;
};
#ifdef MY_INIT
unsigned int sNextID = 0;
#endif
in the file where you have main
#define MY_INIT
#include "data.h"
in all other files where you are including the header, just a plain
#include "data.h"
This will ensure that the line unsigned int sNextID = 0; will be compiled into only one translation unit - the one with main.

Related

Enum class defined in header file does not work in struct which is located in another header file?? C++

SomeHeader.h:
enum class TypeEnum
{
None = 0,
BYTE,
UBYTE,
SHORT,
USHORT
};
AnotherHeader.h
struct Structure
{
TypeEnum type;
};
Throws An Error:
C3646 'type': unknown override specifier
EDIT:
Nobody seems to know the reason so am leaving additional info which might not be related:
TypeEnum has 33 Elements in my real code
It's located on top of the header file
Everything works fine in other headers
Other Structs In AnotherHeader.h With TypeEnum don't work as well
When I define TypeEnum in AnotherHeader.h it says enum class redefinition as it should
Changing to TypeEnum to enum instead of enum class does not work
Other enums don' work as well
Code:
SomeHeader.h:
enum class TypeSpec
{
None = 0,
BYTE,
UBYTE,
SHORT,
USHORT,
INT,
UINT,
FLOAT,
DOUBLE,
VEC2,
VEC3,
VEC4,
VEC2I,
VEC3I,
VEC4I,
VEC2U,
VEC3U,
VEC4U,
VEC2D,
VEC3D,
VEC4D,
MAT2,
MAT3,
MAT4,
MAT2I,
MAT3I,
MAT4I,
MAT2U,
MAT3U,
MAT4U,
MAT2D,
MAT3D,
MAT4D
};
AnotherHeader.h:
struct BufferElement
{
const char* name;
TypeSpec type;
unsigned int size;
unsigned int offset;
bool normalized;
BufferElement() : name("none"), type(TypeSpec::None), size(0), offset(0), normalized(false) {}
BufferElement(TypeSpec _type, const char* _name, bool _normalized = false) :
name(_name), type(_type), size(RenderCommand::getTypeComponentCount(type)), offset(0), normalized(_normalized) {}
};
If you've given us all of AnotherHeader.h, where is the include?
#include "SomeHeader.h"
We do this ALL THE TIME. It's trivial. Define something in one header and #include it at the top of anywhere else you need it. Oh, you should also do this at the top of all .h files:
#pragma once
This keeps the file from being included more than once. (It ignores multiple appearances.)
So your entire SomeHeader would look like:
#pragma once
#include "SomeHeader.h"
struct BufferElement
{
TypeEnum type;
};
Assuming you aren't doing weird stuff with namespaces you haven't actually shown us.

private static data member + template class [duplicate]

What is the best way to initialize a private, static data member in C++? I tried this in my header file, but it gives me weird linker errors:
class foo
{
private:
static int i;
};
int foo::i = 0;
I'm guessing this is because I can't initialize a private member from outside the class. So what's the best way to do this?
The class declaration should be in the header file (Or in the source file if not shared).
File: foo.h
class foo
{
private:
static int i;
};
But the initialization should be in source file.
File: foo.cpp
int foo::i = 0;
If the initialization is in the header file then each file that includes the header file will have a definition of the static member. Thus during the link phase you will get linker errors as the code to initialize the variable will be defined in multiple source files.
The initialisation of the static int i must be done outside of any function.
Note: Matt Curtis: points out that C++ allows the simplification of the above if the static member variable is of const integer type (bool, char, char8_t [since C++20], char16_t, char32_t, wchar_t, short, int, long, long long, or any implementation-defined extended integer types, including any signed, unsigned, and cv-qualified variants.). You can then declare and initialize the member variable directly inside the class declaration in the header file:
class foo
{
private:
static int const i = 42;
};
For a variable:
foo.h:
class foo
{
private:
static int i;
};
foo.cpp:
int foo::i = 0;
This is because there can only be one instance of foo::i in your program. It's sort of the equivalent of extern int i in a header file and int i in a source file.
For a constant you can put the value straight in the class declaration:
class foo
{
private:
static int i;
const static int a = 42;
};
Since C++17, static members may be defined in the header with the inline keyword.
http://en.cppreference.com/w/cpp/language/static
"A static data member may be declared inline. An inline static data member can be defined in the class definition and may specify a default member initializer. It does not need an out-of-class definition:"
struct X
{
inline static int n = 1;
};
For future viewers of this question, I want to point out that you should avoid what monkey0506 is suggesting.
Header files are for declarations.
Header files get compiled once for every .cpp file that directly or indirectly #includes them, and code outside of any function is run at program initialization, before main().
By putting: foo::i = VALUE; into the header, foo:i will be assigned the value VALUE (whatever that is) for every .cpp file, and these assignments will happen in an indeterminate order (determined by the linker) before main() is run.
What if we #define VALUE to be a different number in one of our .cpp files? It will compile fine and we will have no way of knowing which one wins until we run the program.
Never put executed code into a header for the same reason that you never #include a .cpp file.
Include guards (which I agree you should always use) protect you from something different: the same header being indirectly #included multiple times while compiling a single .cpp file.
With a Microsoft compiler[1], static variables that are not int-like can also be defined in a header file, but outside of the class declaration, using the Microsoft specific __declspec(selectany).
class A
{
static B b;
}
__declspec(selectany) A::b;
Note that I'm not saying this is good, I just say it can be done.
[1] These days, more compilers than MSC support __declspec(selectany) - at least gcc and clang. Maybe even more.
int foo::i = 0;
Is the correct syntax for initializing the variable, but it must go in the source file (.cpp) rather than in the header.
Because it is a static variable the compiler needs to create only one copy of it. You have to have a line "int foo:i" some where in your code to tell the compiler where to put it otherwise you get a link error. If that is in a header you will get a copy in every file that includes the header, so get multiply defined symbol errors from the linker.
If you want to initialize some compound type (f.e. string) you can do something like that:
class SomeClass {
static std::list<string> _list;
public:
static const std::list<string>& getList() {
struct Initializer {
Initializer() {
// Here you may want to put mutex
_list.push_back("FIRST");
_list.push_back("SECOND");
....
}
}
static Initializer ListInitializationGuard;
return _list;
}
};
As the ListInitializationGuard is a static variable inside SomeClass::getList() method it will be constructed only once, which means that constructor is called once. This will initialize _list variable to value you need. Any subsequent call to getList will simply return already initialized _list object.
Of course you have to access _list object always by calling getList() method.
C++11 static constructor pattern that works for multiple objects
One idiom was proposed at: https://stackoverflow.com/a/27088552/895245 but here goes a cleaner version that does not require creating a new method per member.
main.cpp
#include <cassert>
#include <vector>
// Normally on the .hpp file.
class MyClass {
public:
static std::vector<int> v, v2;
static struct StaticConstructor {
StaticConstructor() {
v.push_back(1);
v.push_back(2);
v2.push_back(3);
v2.push_back(4);
}
} _staticConstructor;
};
// Normally on the .cpp file.
std::vector<int> MyClass::v;
std::vector<int> MyClass::v2;
// Must come after every static member.
MyClass::StaticConstructor MyClass::_staticConstructor;
int main() {
assert(MyClass::v[0] == 1);
assert(MyClass::v[1] == 2);
assert(MyClass::v2[0] == 3);
assert(MyClass::v2[1] == 4);
}
GitHub upstream.
Compile and run:
g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
See also: static constructors in C++? I need to initialize private static objects
Tested on Ubuntu 19.04.
C++17 inline variable
Mentioned at: https://stackoverflow.com/a/45062055/895245 but here is a multifile runnable example to make it even clearer: How do inline variables work?
This awesome C++17 feature allow us to:
conveniently use just a single memory address for each constant
store it as a constexpr: How to declare constexpr extern?
do it in a single line from one header
main.cpp
#include <cassert>
#include "notmain.hpp"
int main() {
// Both files see the same memory address.
assert(&notmain_i == notmain_func());
assert(notmain_i == 42);
}
notmain.hpp
#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP
inline constexpr int notmain_i = 42;
const int* notmain_func();
#endif
notmain.cpp
#include "notmain.hpp"
const int* notmain_func() {
return &notmain_i;
}
Compile and run:
g++ -c -o notmain.o -std=c++17 -Wall -Wextra -pedantic notmain.cpp
g++ -c -o main.o -std=c++17 -Wall -Wextra -pedantic main.cpp
g++ -o main -std=c++17 -Wall -Wextra -pedantic main.o notmain.o
./main
GitHub upstream.
I don't have enough rep here to add this as a comment, but IMO it's good style to write your headers with #include guards anyway, which as noted by Paranaix a few hours ago would prevent a multiple-definition error. Unless you're already using a separate CPP file, it's not necessary to use one just to initialize static non-integral members.
#ifndef FOO_H
#define FOO_H
#include "bar.h"
class foo
{
private:
static bar i;
};
bar foo::i = VALUE;
#endif
I see no need to use a separate CPP file for this. Sure, you can, but there's no technical reason why you should have to.
You can also include the assignment in the header file if you use header guards. I have used this technique for a C++ library I have created. Another way to achieve the same result is to use static methods. For example...
class Foo
{
public:
int GetMyStatic() const
{
return *MyStatic();
}
private:
static int* MyStatic()
{
static int mStatic = 0;
return &mStatic;
}
}
The above code has the "bonus" of not requiring a CPP/source file. Again, a method I use for my C++ libraries.
The linker problem you encountered is probably caused by:
Providing both class and static member definition in header file,
Including this header in two or more source files.
This is a common problem for those who starts with C++. Static class member must be initialized in single translation unit i.e. in single source file.
Unfortunately, the static class member must be initialized outside of the class body. This complicates writing header-only code, and, therefore, I am using quite different approach. You can provide your static object through static or non-static class function for example:
class Foo
{
// int& getObjectInstance() const {
static int& getObjectInstance() {
static int object;
return object;
}
void func() {
int &object = getValueInstance();
object += 5;
}
};
I follow the idea from Karl. I like it and now I use it as well.
I've changed a little bit the notation and add some functionality
#include <stdio.h>
class Foo
{
public:
int GetMyStaticValue () const { return MyStatic(); }
int & GetMyStaticVar () { return MyStatic(); }
static bool isMyStatic (int & num) { return & num == & MyStatic(); }
private:
static int & MyStatic ()
{
static int mStatic = 7;
return mStatic;
}
};
int main (int, char **)
{
Foo obj;
printf ("mystatic value %d\n", obj.GetMyStaticValue());
obj.GetMyStaticVar () = 3;
printf ("mystatic value %d\n", obj.GetMyStaticValue());
int valMyS = obj.GetMyStaticVar ();
int & iPtr1 = obj.GetMyStaticVar ();
int & iPtr2 = valMyS;
printf ("is my static %d %d\n", Foo::isMyStatic(iPtr1), Foo::isMyStatic(iPtr2));
}
this outputs
mystatic value 7
mystatic value 3
is my static 1 0
Also working in privateStatic.cpp file :
#include <iostream>
using namespace std;
class A
{
private:
static int v;
};
int A::v = 10; // possible initializing
int main()
{
A a;
//cout << A::v << endl; // no access because of private scope
return 0;
}
// g++ privateStatic.cpp -o privateStatic && ./privateStatic
What about a set_default() method?
class foo
{
public:
static void set_default(int);
private:
static int i;
};
void foo::set_default(int x) {
i = x;
}
We would only have to use the set_default(int x) method and our static variable would be initialized.
This would not be in disagreement with the rest of the comments, actually it follows the same principle of initializing the variable in a global scope, but by using this method we make it explicit (and easy to see-understand) instead of having the definition of the variable hanging there.
One "old-school" way to define constants is to replace them by a enum:
class foo
{
private:
enum {i = 0}; // default type = int
enum: int64_t {HUGE = 1000000000000}; // may specify another type
};
This way doesn't require providing a definition, and avoids making the constant lvalue, which can save you some headaches, e.g. when you accidentally ODR-use it.
Here are all possibilities and errors in one simple example ...
#ifndef Foo_h
#define Foo_h
class Foo
{
static const int a = 42; // OK
static const int b {7}; // OK
//static int x = 42; // ISO C++ forbids in-class initialization of non-const static member 'Foo::x'
//static int y {7}; // ISO C++ forbids in-class initialization of non-const static member 'Foo::x'
static int x;
static int y;
int m = 42;
int n {7};
};
// Foo::x = 42; // error: 'int Foo::x' is private
int Foo::x = 42; // OK in Foo.h if included in only one *.cpp -> *.o file!
int Foo::y {7}; // OK
// int Foo::y {7}; // error: redefinition of 'int Foo::y'
// ONLY if the compiler can see both declarations at the same time it,
// OTHERWISE you get a linker error
#endif // Foo_h
But better place this in Foo.cpp. This way you can separately compile each file and link them later, otherwise Foo:x will be present in multiple object files and cause a linker error. ...
// Foo::x = 42; // error: 'int Foo::x' is private, bad if Foo::X is public!
int Foo::x = 42; // OK in Foo.h if included in only one *.cpp -> *.o file!
int Foo::y {7}; // OK
Does this serves your purpose?
//header file
struct MyStruct {
public:
const std::unordered_map<std::string, uint32_t> str_to_int{
{ "a", 1 },
{ "b", 2 },
...
{ "z", 26 }
};
const std::unordered_map<int , std::string> int_to_str{
{ 1, "a" },
{ 2, "b" },
...
{ 26, "z" }
};
std::string some_string = "justanotherstring";
uint32_t some_int = 42;
static MyStruct & Singleton() {
static MyStruct instance;
return instance;
}
private:
MyStruct() {};
};
//Usage in cpp file
int main(){
std::cout<<MyStruct::Singleton().some_string<<std::endl;
std::cout<<MyStruct::Singleton().some_int<<std::endl;
return 0;
}
I just wanted to mention something a little strange to me when I first encountered this.
I needed to initialize a private static data member in a template class.
in the .h or .hpp, it looks something like this to initialize a static data member of a template class:
template<typename T>
Type ClassName<T>::dataMemberName = initialValue;

Static variables and initialization

I am trying to reach a static variable declared in MyClass.h from MyClass.cpp. But I get following errors.
I made a research but still have no clue why my code does not compile. I use visual studio 2013.
MyClass.h
#ifndef __MyClass_h_
#define __MyClass_h_
class MyClass {
static int x;
public:
static int y;
};
#endif
MyClass.cpp
#include "MyClass.h"
void MyClass::sor() (const string& var1, const unsigned count) const {
// What goes here? See below for what I have tried
}
So, if I use:
int MyClass::x=8;
This says int MyClass::x redefinition and MyClass::x 'MyClass::x' : definition or redeclaration illegal in current scope
If I use:
MyClass::x=8;
This gives the error 1 unresolved external.
If I use:
MyClass::y=8;
This also gives the error 1 unresolved external.
If I use:
int MyClass::y=8;
This says int MyClass::y redefinition and 'MyClass::y' : definition or redeclaration illegal in current scope
You need to understand you don't have a static variable in a header, how other answers suggest. You have a static member of a class, which is perfectly fine.
In order to access it you write: MyClass::x. You need to initialize it also.
Unrelated to the static member, you need to declare the method also:
header:
#ifndef __MyClass_h_
#define __MyClass_h_
class MyClass {
static int x;
public:
static int y;
void sor() (const string& var1, const unsigned count) const;
};
#endif
source file:
#include "MyClass.h"
int MyClass::x = 0; // intialization
void MyClass::sor() (const string& var1, const unsigned count) const {
MyClaxx::x = 11; // access it
}
You have a declaration for the static variable but don't have the definition for it. In order to use static class members you should define them in the corresponding translation unit. You can't do it in the header file because it will violate ODR(one definition rule) so you should define it in the .cpp file to confrom the aforementioned rule.
So you have to put int MyClass::x = 0; in your cpp file in global scope(or under the namespace if you have one) to get it working. Note, that you could use whatever value insted of 0 or even didn't provide any(in this case it will be 0 anyway, due to special treatment of global(static) variables.)
When static variable is declared in a header file is its scope limited to .h file or across all units.
Refer here for source
This is simple. When you declare a static variable in a header file, it's scope is limited to header file. When you going to use that static variable in a .cpp file you getting an error like this. It is because you didn't give the definition of the static variable. So in any of the .cpp file you need to give the definition of static variable. ex :
.h file
class MyClass {
static int x;
.....
}
Top of the .cpp file you should define the static variable like this.
#include "MyClass.h"
int MyClass::x = 0 ;
void MyClass::sor() (const string& var1, const unsigned count) const {
MyClass::x = 8 ; // you can access without any issue
}

How to use global static variable in c++

I have static int defaultvalue = 1 in my .cpp file and I have a static class function like this which uses the global static variable defaultvalue in the same file.
//static function
int Myclass::func(int rate)
{
int finalrate = defaultvalue;
switch(rate)
{
case 2:
finalrate=2;
break;
default:
break;
}
return finalrate;
}
When I tried to compile this.I got an error saying undefined reference to Myclass::defaultvalue.
Can some one help me out.Thanks.
You need to declare it as extern in h and then declare it's "body" in .cpp.
For your case :
in the .h
extern int defaultValue;
in the .cpp
int MyClass::defaultValue=0;
If that variable is defined in a different module, then you will have to use the extern keyword in your current module ahead of any references to it, e.g.,
extern int defaultValue;
That will notify the compiler that it is defined elsewhere. At least one module should have a non-extern definition
int defaultvalue;
or the linked will be unhappy.
Alternately, you could put a constant definition in a .h file, and #include that .h file in each of your .cpp sources. For example:
// File defval.h
const int defaultvalue = 42;
and then in your source, use
#include defval.h
Or just put it in the class:
class Myclass
{
public:
static int func(int rate);
static const int defaultvalue = 1 ;
};
I think that te best approach is to put static member into class and then not forget to initialize it in cpp file.
file.h
class Myclass
{
public:
static int func(int rate);
static int defaultvalue;
};
file.cpp
int MyClass::defaultValue=0;
int Myclass::func(int rate)
{
...
}

Using static const + const as array bound

I'm doing something like this
Class.hpp:
class Class {
private:
static const unsigned int arraySize;
int ar[arraySize+2];
};
Class.cpp:
#include <Class.hpp>
const unsigned int arraySize = 384;
The compiler (q++, a c++ compiler for the QNX OS based on g++) gives me error: array bound is not an integer constant while compiling a unit including Class.hpp (not while compiling Class.cpp).
Why isn't that working? I know that a static const member can be used as an array bound, guaranteed by the C++ standard (see this anwser). But why doesn't the compiler see the result of static const + const as a constant?
This is good code which should have been accepted by the compiler:
class Class {
const static int arraySize = 384;
int ar[arraySize+2];
};
and if it isn't, your compiler is broken.
However, if you move actual constant out of the header file to selected translation unit, that invalidates the code.
// Class.h
class Class {
const static int arraySize;
int ar[arraySize+2]; // ERROR
};
// Class.cpp
const int Class::arraySize = 384;
This is because the size of your Class object cannot be determined at compile time from the data available in the header alone. This is not exactly right reason, but reasoning along these lines helps to understand compilation errors such as this.
To avoid making such mistakes, you can replace static const int with an enum, e.g.
class Class {
enum { arraySize = 384 };
int ar[arraySize+2];
};
I'm surprised this actually compiles on gcc, as a comment says. Since the 384 isn't in the header file, the size of the Class is not known to other compilation units. It might not matter in some compilation units depending on how/if they are using Class, but I can't imagine this compiling:
// this is a source file called, say, blah.cpp
#include <Class.hpp>
void someFunc()
{
void *mem = malloc(sizeof(Class)); // size is not known, so this can't compile
// do something with mem
}
You need to have in your .hpp:
class Class {
private:
static const unsigned int arraySize = 384;
int ar[arraySize+2];
};
.. as it is in the OP that you link to here.