C++ where to initialize static const - c++

I have a class
class foo {
public:
foo();
foo( int );
private:
static const string s;
};
Where is the best place to initialize the string s in the source file?

Anywhere in one compilation unit (usually a .cpp file) would do:
foo.h
class foo {
static const string s; // Can never be initialized here.
static const char* cs; // Same with C strings.
static const int i = 3; // Integral types can be initialized here (*)...
static const int j; // ... OR in cpp.
};
foo.cpp
#include "foo.h"
const string foo::s = "foo string";
const char* foo::cs = "foo C string";
// No definition for i. (*)
const int foo::j = 4;
(*) According to the standards you must define i outside of the class definition (like j is) if it is used in code other than just integral constant expressions. See David's comment below for details.

Since C++17 the inline specifier also applies to variables. You can now define static member variables in the class definition:
#include <string>
class foo {
public:
foo();
foo( int );
private:
inline static const std::string s { "foo" };
};

In a translation unit within the same namespace, usually at the top:
// foo.h
struct foo
{
static const std::string s;
};
// foo.cpp
const std::string foo::s = "thingadongdong"; // this is where it lives
// bar.h
namespace baz
{
struct bar
{
static const float f;
};
}
// bar.cpp
namespace baz
{
const float bar::f = 3.1415926535;
}

Static members need to be initialized in a .cpp translation unit at file scope or in the appropriate namespace:
const string foo::s( "my foo");

Only integral values (e.g., static const int ARRAYSIZE) are initialized in header file because they are usually used in class header to define something such as the size of an array. Non-integral values are initialized in implementation file.

Related

C++ const static member is not identified when trying to use it to initialize an array

I want to create a constant static int variable to specify the range of an array. I'm running into problems and getting errors saying that the variable is not a member of the class, but I can print out the variable in main using ClassName::staticVarName.
I cannot figure out how to properly set up a static variable that belongs to a class so that it can be used to initialize an array. The variable prints in main, but for some reason it will not compile when I try to use it to define a classes's array field's range.
error: class "RisingSunPuzzle" has no member "rows"
error: class "RisingSunPuzzle" has no member "cols"
header file for class:
#pragma once
#include<map>
#include<string>
#include<memory>
class RisingSunPuzzle
{
private:
bool board[RisingSunPuzzle::rows][RisingSunPuzzle::cols];
public:
RisingSunPuzzle();
~RisingSunPuzzle();
static const int cols;
static const int rows;
void solvePuzzle();
void clearboard();
};
cpp file for class:
#include "RisingSunPuzzle.h"
const int RisingSunPuzzle::cols = 5;
const int RisingSunPuzzle::rows = 4;
RisingSunPuzzle::RisingSunPuzzle()
{
}
RisingSunPuzzle::~RisingSunPuzzle()
{
}
void RisingSunPuzzle::solvePuzzle()
{
}
void RisingSunPuzzle::clearboard()
{
}
The names of data members that are referred to must be declared before the data members that refer them to.
Also the static constants have to be initializes.
You can reformat the class the following way
class RisingSunPuzzle
{
public:
static const int cols = 5;
static const int rows = 4;
private:
bool board[RisingSunPuzzle::rows][RisingSunPuzzle::cols];
public:
RisingSunPuzzle();
~RisingSunPuzzle();
void solvePuzzle();
void clearboard();
};
//...
There is no need to define the constants if they are not ODR used. Nevertheless you can define them (without initializers) like
const int RisingSunPuzzle::cols;
const int RisingSunPuzzle::rows;

templates and static objects (undefined reference & required from)

I'm implementing some ideas using templates and static members. Although the "real" code produces another error, this is the one which i still have on a toy example code
#include <string>
#include <iostream>
template<int dim>
class Class1 {
public:
Class1() {};
~Class1() {};
void foo() {
std::cout<<"foo-1"<<std::endl;
}
protected:
std::string name;
};
template<int dim>
class Class2 : public Class1<dim>
{
public:
Class2(const int & a, const int &b) :
number( Class2<dim>::id_generator++ )
{
Class1<dim>::name = "My-name";
foo(); // (1)
};
void foo() {
Class1<dim>::foo();
std::cout<<"foo-2"<<std::endl;
}
private:
const unsigned int number;
static unsigned int id_generator;
};
int main()
{
int a = 1, b=2;
Class2<2> class2(a,b); // (2)
}
with the linker error:
undefined reference to `Class2<2>::id_generator'
rea-life example produces 2 errors
(1) required from 'Class2<dim>::Class2(int, int) [with int dim = 3]'
(2) required from here.
that real-life errors tell me absolutely nothing at all! :(
I hope if the toy-problem is solved, the real-life one will be gone too,
but if anyone has any ideas on the "real-life" errors (those 2 lines) in the context of the structure, pls, let me know.
You forgot to add a definition for your static data member id_generator. Add this at global namespace level:
template<int dim>
unsigned int Class2<dim>::id_generator = 0;
With this addition, you can see your code correctly compiling and linking here.
Well, as the error message says, there is no definition of the static data member. If this was an ordinary class, you'd put the definition in a source file:
// header:
class C {
static int i;
};
// source:
int C::i = 3;
A template is a pattern; the compiler uses it to generate code. So what you want to end up with when the compiler instantiates the template is something like the preceding code. But template code goes in headers, not source files, so you write it like this:
// header:
template <class T>
class C {
static int i;
};
template <class T>
int C<T>::i = 3;

Static member in C++ programming

I'm trying to create a C++ class which can work as a holder for my project, so have implemented my class members and functions static, but I don't know why compiler can recognize the _nTriggerMode inside the setTriggerMode.
Here is my header file:
#pragma once
class GrabberOptions
{
private:
static int _nTriggerMode;
static int _nExposureInMicroSec;
static double _dFramesPerSecond;
static int _nExsysncOn;
public:
GrabberOptions(void);
~GrabberOptions(void);
static void setTriggerMode(int triggerMode);
static void setExposureInMicroSec(int exposureMicroSec);
static void setFramePerSecond(double framePerSec);
static void setExsysncOn(int exsysncOn);
static int getTriggerMode();
static int getExposureInMicroSec();
static double getFramePerSecond();
static int getExsysncOn();
};
And here is the .ccp file:
#include "StdAfx.h"
#include "GrabberOptions.h"
int GrabberOptions::_nTriggerMode;
int GrabberOptions::_nExposureInMicroSec;
double GrabberOptions::_dFramesPerSecond;
int GrabberOptions::_nExsysncOn;
GrabberOptions::GrabberOptions(void)
{
_nTriggerMode = GRABBER_CONTROLLED;
_nExposureInMicroSec = 20;
_dFramesPerSecond = 1000;
_nExsysncOn = 1;
}
GrabberOptions::~GrabberOptions(void)
{
}
void setTriggerMode(int triggerMode){
_nTriggerMode=triggerMode;
}
Please give me some idea of how to use static.
static class member variables must be defined outside of the class definition:
// .h file
class GrabberOptions
{
private:
static double _dFramesPerSecond; // declaration
// .cpp file
double GrabberOptions::_dFramesPerSecond = 1000; // definition
You need to initialize the static outside the class definition, in a single translation unit (usually your corresponding implementation file):
#include "StdAfx.h"
#include "GrabberOptions.h"
double GrabberOptions::_dFramesPerSecond; //initializes to 0
//double GrabberOptions::_dFramesPerSecond = 1337; //if you want a different value
GrabberOptions::GrabberOptions(void)
{
// _nTriggerMode = GRABBER_CONTROLLED;
// _nExposureInMicroSec = 20;
_dFramesPerSecond = 1000;
// _nExsysncOn = 1;
}
GrabberOptions::~GrabberOptions(void)
{
}
The static member variables of a class are shared by all instances of a class. They are occasionally useful, but this is probably not an example. Static member functions can only access static member variables.
Your class design shown by the commented out code has no per-instance data; everything is static. That is essentially never a good design in C++.

I'm trying to declare a constant string in my C++ class, but I get an "Invalid in-class assignment", and I don't understand why

here's the code:
#include <string>
class Config {
public:
static const std::string asdf = "hello world!";
}
I can't diagnose why this won't work
Only integral types can be initialized in the class (presuming they're declared as static const).
So do this:
//Config.h
class Config
{
public:
static const std::string asdf; //declaration
static const int demo_integral = 100; //initialization is allowed!
}
//Config.cpp
const std::string Config::asdf = "hello world!"; //definition & initialization
const int Config::demo_integral; //already initialized in the class!
Definitions should be in .cpp file, or else you will get multiple definition error if you define them in the header file itself and then you include the header file in multiple files!
You cannot do this.
As it is static, it must be defined outside the class ( const std::string asdf inside your class is only declaration, because of the static)
In your case:
const std::string Config::asdf = "hello world!"
You should initialize all data members inside constructor, not like this:
class A
{
var_t var = value;
};
Apart from integral types, static const members cannot be initialized within the class definition scope. You have to split it, as follows.
In header file:
#include <string>
class Config {
public:
static const std::string asdf;
};
And in .cpp file
const std::string Config::asdf = "hello world!";
You have to declare it outside of the class:
#include <string>
class Config {
public:
static const std::string asdf = "hello world!";
}
const std::string Config::asdf = "hello world";
Also look here.
From:
http://cplusplus.syntaxerrors.info/index.php?title=Invalid_in-class_initialization_of_static_data_member_of_non-integral_type_%E2%80%98const_char*%E2%80%99
You are only allowed to first assign variables that are enumeration types or"integral" types -- int, char, long, etc -- inside a class definition. Char* is not an integral type, so you can only assign to it in global scope.
It is possible for you to do this as a workaround:
#include <string>
class Config {
public:
static const std::string asdf()
{
return "Hello World!";
}
};

How to access static members of a class?

I am starting to learn C++ and Qt, but sometimes the simplest code that I paste from a book results in errors.
I'm using g++4.4.2 on Ubuntu 10.04 with QtCreator IDE. Is there a difference between the g++ compiler syntax and other compilers? For example when I try to access static members something always goes wrong.
#include <iostream>
using namespace std;
class A
{
public:
static int x;
static int getX() {return x;}
};
int main()
{
int A::x = 100; // error: invalid use of qualified-name 'A::x'
cout<<A::getX(); // error: : undefined reference to 'A::x'
return 0;
}
I think it's exactly the same as declared here and here (isn't it?). So what's wrong with the above code?
You've declared the static members fine, but not defined them anywhere.
Basically what you've said "there exists some static member", but never set aside some memory for it, you need:
int A::x = 100;
Somewhere outside the class and not inside main.
Section [9.4.2]
Static Data Members
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. In the definition at namespace scope, the name of the static data member shall be qualified by its class name using the :: operator
You need to define the static member variable of the class outside the class as static member variables require declaration as well as definition.
#include <iostream>
using namespace std;
class A
{
public:
static int x;
static int getX() {return x;}
};
int A::x; // STATIC MEMBER VARIABLE x DEFINITION
int main()
{
A::x = 100; // REMOVE int FROM HERE
cout<<A::getX();
return 0;
}
Try:
#include <iostream>
using namespace std;
class A
{
public:
// This declares it.
static int x;
static int getX(){return x;}
};
// Now you need an create the object so
// This must be done in once source file (at file scope level)
int A::x = 100;
int main()
{
A::x = 200;
// Notice no 'int' keyword before A::x on this line. You can modify A::x
cout<<A::getX(); // Should work
return 0;
}
The definition of static member variables must live at file scope, i.e. outside all functions, etc.
Try this example:
#include<iostream>
using namespace std;
class check
{
static int a;
public:
void change();
} ;
int check::a=10;
void check::change()
{
a++;
cout<<a<<"\n";
}
int main()
{
int i,j;
check c;
check b;
c.change();
b.change();
return 0;
}
Now you have worked out how to use static class members I will advise you that you should generally use them only in the following circumstances:
For use in templates. So in your example you could have GetX() in different classes and in a template somewhere you would use
template< typename T >
int func()
{
return T::GetX();
}
although obviously more elaborate. But here your static function being in a class serves a purpose.
Where the function needs access to the class, i.e. to private members. You could make it a friend but you may as well make it static. Often the case in callbacks.
The rest of the time you can probably use compilation-unit level functions and variables which has the advantage of taking your members out of the header (particularly if they are private). The less implementation detail you give the better.
You can use the inline keyword since c++ 17 in front of static members to avoid a definition outside of class scope. Your code should now look like this:
#include <iostream>
using namespace std;
class A
{
public:
inline static int x;
static int getX() {return x;}
};
int main()
{
A::x = 100; //Works now
cout<<A::getX()<<'\n';
return 0;
}
Case 1: static variable
As we all know, defining a static variable inside a class which will throw compilation error. E.g. below
class Stats
{
public:
static int AtkStats[3];
*static int a =20;* // Error: defining a value for static variable
};
int Stats::AtkStats[3] = {10, 0, 0};
Output:
error: ISO C++ forbids in-class initialization of non-const static member 'Stats::a'
Case 2: const static variable
For const static variable, we can define a value either inside a class or Outside class.
class Stats
{
public:
static const int AtkStats[3];
static const int a =20; // Success: defining a value for a const static
};
const int Stats::AtkStats[3] = {10, 0, 0};
const int Stats::a = 20; // we can define outside also
Output:
Compilation success.