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.
Related
I found a similar code like the one shown below, and two things confuse me. The first one, is it possible to have an object of the class, inside of the definition of the class, as in the example below in code 1? I though this was not possible, but maybe the static keyword is making this possible. Is this right? what is it actually happening here?
The second one, I learned that we can access static member variables and static member functions of a class just by calling the class name and the scope resolution operator (and the member we want). Apparently, the way described in code1 is an alternative manner of doing this. So, what is the main difference (or advantage) of doing it this way? In other words, what is the difference between code 1 and code 2?
//CODE 1
namespace LOGGER {
class Logger;
}
class LOGGER::Logger {
void foo(){}
public:
static Logger logger;
};
int main()
{
LOGGER::Logger::logger.foo();
}
//CODE 2
namespace LOGGER {
class Logger;
}
class LOGGER::Logger {
public:
static void foo(){}
};
int main()
{
LOGGER::Logger::foo();
}
I have a class that contains a static member variable, I would like to initialize it using an anonymous namespace in the .cpp file just like what I saw in the link :Where to put constant strings in C++: static class members or anonymous namespaces
But I am getting an error saying the current member rate cannot be defined in the scope. Why?
//A.h
namespace myclass
{
class A
{
private:
static double rate;
};
}
//A.cpp
namespace myclass
{
namespace{
double A::rate = 99.9;
}
}
You can't: it's already a qualified member of a class:
//A.cpp
namespace myclass
{
double A::rate = 99.9;
}
will do. The static will already stick, because of the declaration.
The confusion might be because static has different meanings:
What is external linkage and internal linkage?
However, a static class member doesn't have anything to do with visibility (internal/external linkage). Instead it has to with storage duration.
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.
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.
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.