I have the following code:
class gptr_timer {
private:
static qtimer_t gptr_get_timer;
public:
static void create_gptr_get_timer(){
gptr_get_timer = qtimer_create();
}
static void destroy_gptr_get_timer(){
qtimer_destroy(gptr_get_timer);
}
static void start_gptr_get_timer(){
qtimer_start(gptr_get_timer);
}
static void stop_gptr_get_timer(){
qtimer_stop(gptr_get_timer);
}
static double get_gptr_get_time(){
return qtimer_secs(gptr_get_timer);
}
};
Which produces the following compile error:
/home/knusbau2/barnes/qppl/gptr.h:24: undefined reference to `ppl::gptr_timer::gptr_get_timer'
I'm a little confused, as I clearly have gptr_get_timer defined.
By adding a definition:
class gptr_timer { /* ... */ }; // class definition;
// *delcares* static member variables
qtimer_t gptr_timer::gptr_get_timer; // *define* static member variables
The static member definition has to go into one single translation unit, while the class definition is usually in a header. Beware.
The member definition is also the place for initialization, except in a few special cases (namely static constant expressions) which can be initialized inside the class definition.
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'd like to have a class that has static members to itself, but I can't figure how to do that. Is that even possible?
I get the error:
only static const integral data members can be initialized within a class
Code:
namespace misc
{
class CData
{
public:
CData( ) { };
CData( int d );
CData& operator = ( const CData& d );
static const CData FIRST = CData( 512 ); //how?
private:
int data;
};
}
As I use FIRST a lot I would like to statically access it using misc::CData::FIRST without the need to declare it somewhere in the scope. Is that by any chance possible?
... without the need to declare it somewhere in the scope. Is that by any chance possible?
No, it's not possible without declaring it (which you already tried to do in your class declaration). You probably meant, without defining it outside your class declaration. Again the answer is no.
You have to separate declaration and definition for this case (it only works with primitive integral types like int to initialize these directly in the class declaration).
First have a simple declaration in your class declaration (usually something like CData.hpp)
namespace misc {
class CData {
public:
CData( ) { };
CData( int d );
CData& operator = ( const CData& d );
static const CData& FIRST;
private:
int data;
};
}
and then define it in a separate compilation unit (usually something like CData.cpp)
namespace misc {
const CData& CData::FIRST = CData( 512 );
}
For non-integral data, something like this is preferred since it avoids the static initialization fiasco.
static const CData FIRST()
{
static CData first(512); //only initialized once, when first requested
return first;
}
... without the need to declare it somewhere in the scope. Is that by
any chance possible?
No.
C++ Standard n3337 § 9.4.2/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. (...)
You can declare a static data member in class:
namespace misc {
class CData {
public:
//...
static const CData FIRST; // declaration
//...
}
and define it in (exactly) one of the .cpp files:
namespace misc {
CData CData::FIRST = CData( 512 ); // definition
}
This is preferred solution, however you need to have this definition out of your class. You could have defined the member in class if it was of an integral type
C++ Standard n3337 § 9.4.2/3 says
If a non-volatile const static data member is of integral or
enumeration type, its declaration in the class definition can specify
a brace-or-equal-initializer in which every initializer-clause that is
an assignment- expression is a constant expression (...)
I am currently doing a checker for the top level domains of email addresses. In order to check, I am comparing it to a list that is a text file. I want to import the list into a static map container. However, when I try to instantiate it, it says that it cannot be defined in the current scope. Why is that?
This is some my header file:
class TldPart {
public:
static void LoadTlds();
private:
static map<string,bool> Tld;
}
Here is the implementation in the cpp:
void TldPart::LoadTlds()
{
map<string,bool> Tld;
...
}
It is telling me that ValidTld cannot be defined in the LoadTlds function.
Static members of a class exist outside of an object. You should define and initialize static member outside of the class.
Here we define and initialize a static class member:
header-file:
#pragma once
#include <map>
#include <string>
class TldPart {
public:
static void LoadTlds();
private:
static std::map<std::string, bool> tld;
};
your cpp-file:
#include "external.h"
std::map<std::string,bool> TldPart::tld;
void TldPart::LoadTlds()
{
tld.insert(std::make_pair("XX", true));
}
And don't forget semicolon at the end of the class.
EDIT: You can provide in-class initializers for static members of const integral type or static members that are constexprs and has literal type.
I want to write a little Singleton class that looks like:
#include <vector>
class Interpreter {
private:
static Interpreter* interInstance;
Interpreter() {}
public:
static Interpreter* getInstance();
~Interpreter() {}
};
Interpreter* Interpreter::interInstance = 0;
Interpreter* Interpreter::getInstance(){
if (!interInstance)
interInstance = new Interpreter();
return interInstance;
}
But this will produce this exception:
multiple definition of `Interpreter::getInstance()
This error can be corrected by wrapping the class and the function in one namespace.
But I don't really understand why I need a namespace.
There is one declaration of getInstance() and one implementation, no?
Move the definition outside the header, in an implementation file, for both the member initialization and the method:
Interpreter.h
class Interpreter {
private:
static Interpreter* interInstance;
Interpreter() {}
public:
static Interpreter* getInstance();
~Interpreter() {}
};
Interpreter.cpp
#include "Interpreter.h"
Interpreter* Interpreter::interInstance = 0;
Interpreter* Interpreter::getInstance(){
if (!interInstance)
interInstance = new Interpreter();
return interInstance;
}
Inside a class or struct definition, static doesn't give symbols internal linkage as it does outside, so you're breaking the one definition rule.
If multiple translation units include a header that contains non-inline methods or define the same symbol, you'll run into multiple definition.
I have a class exposing a static function in myclass.hpp
class MyClass {
public:
static std::string dosome();
};
Well, in myclass.cpp what should I write:
this:
std::string MyClass::dosome() {
...
}
or this:
static std::string MyClass::dosome() {
...
}
I guess I should not repeat the static keyword... is it correct?
C++ compiler will not allow this:
static std::string MyClass::dosome() {
...
}
since having static in a function definition means something completely different - static linkage (meaning the function can only be called from the same translation unit).
Having static in a member function declaration is enough.
Do not repeat the static keyword. To do so will result in an error.
Yes. The static keyword should not be used when defining a function body outside the class definition.