Are static variables in a base class shared by all derived classes?
Solution 1
They will each share the same instance of staticVar
.
In order for each derived class to get their own static variable, you'll need to declare another static variable with a different name.
You could then use a virtual pair of functions in your base class to get and set the value of the variable, and override that pair in each of your derived classes to get and set the "local" static variable for that class. Alternatively you could use a single function that returns a reference:
class Base {
static int staticVarInst;
public:
virtual int &staticVar() { return staticVarInst; }
}
class Derived: public Base {
static int derivedStaticVarInst;
public:
virtual int &staticVar() { return derivedStaticVarInst; }
}
You would then use this as:
staticVar() = 5;
cout << staticVar();
Solution 2
To ensure that each class has its own static variable, you should use the "Curiously recurring template pattern" (CRTP).
template <typename T>
class Base
{
static int staticVar;
};
template <typename T> int Base<T>::staticVar(0);
class DerivedA : public Base<DerivedA> {};
class DerivedB : public Base<DerivedB> {};
Solution 3
They will share the same instance.
You'll need to declare separate static variables for each subclass, or you could consider a simple static map in which you could store variables that are referenced by derived classes.
Edit: A possible solution to this would be to define your base class as a template. Having a static variable defined in this template would mean that each derived class will have it's own instance of the static.
Solution 4
There is only one staticVar
in your case: Base::staticVar
When you declare a static variable in a class, the variable is declared for that class alone. In your case, DerivedA can't even see staticVar
(since it's private, not protected or public), so it doesn't even know there is a staticVar
variable in existence.
Solution 5
I know that this question has already been answered but I would like to provide a small example of inheritance with static members. This is a very nice way to demonstrate the usefulness as well as what is happening with the static variables and the respective constructors.
FooBase.h
#ifndef FOO_BASE_H
#define FOO_BASE_H
#include <string>
class FooBase {
protected:
std::string _nameAndId;
private:
std::string _id;
static int _baseCounter;
public:
std::string idOfBase();
virtual std::string idOf() const = 0;
protected:
FooBase();
};
#endif // !FOO_BASE_H
FooBase.cpp
#include "FooBase.h"
#include <iostream>
int FooBase::_baseCounter = 0;
FooBase::FooBase() {
_id = std::string( __FUNCTION__ ) + std::to_string( ++_baseCounter );
std::cout << _id << std::endl;
}
std::string FooBase::idOfBase() {
return _id;
}
std::string FooBase::idOf() const {
return "";
} // empty
DerivedFoos.h
#ifndef DERIVED_FOOS_H
#define DERIVED_FOOS_H
#include "FooBase.h"
class DerivedA : public FooBase {
private:
static int _derivedCounter;
public:
DerivedA();
std::string idOf() const override;
};
class DerivedB : public FooBase {
private:
static int _derivedCounter;
public:
DerivedB();
std::string idOf() const override;
};
#endif // !DERIVED_FOOS_H
DerivedFoos.cpp
#include "DerivedFoos.h"
#include <iostream>
int DerivedA::_derivedCounter = 0;
int DerivedB::_derivedCounter = 0;
DerivedA::DerivedA() : FooBase() {
_nameAndId = std::string( __FUNCTION__ ) + std::to_string( ++DerivedA::_derivedCounter );
std::cout << _nameAndId << std::endl;
}
std::string DerivedA::idOf() const {
return _nameAndId;
}
DerivedB::DerivedB() : FooBase() {
_nameAndId = std::string( __FUNCTION__ ) + std::to_string( ++DerivedB::_derivedCounter );
std::cout << _nameAndId << std::endl;
}
std::string DerivedB::idOf() const {
return _nameAndId;
}
main.cpp
#include "DerivedFoos.h"
int main() {
DerivedA a1;
DerivedA a2;
DerivedB b1;
DerivedB b2;
system( "PAUSE" );
return 0;
}
If __FUNCTION__
is not working for you in your constructors then you can use something similar that can replace it such as __PRETTY_FUNCTION__
or __func__
, or manually type out each class's name :(
.
Comments
-
mpen almost 4 years
If I have something like
class Base { static int staticVar; } class DerivedA : public Base {} class DerivedB : public Base {}
Will both
DerivedA
andDerivedB
share the samestaticVar
or will they each get their own?If I wanted them to each have their own, what would you recommend I do?
-
mpen almost 15 yearsIn this case, by "derived" you mean Base<A> would have a different static var than Base<B>, but Derived<A> would still share with Base<A> no?
-
mpen almost 15 yearsI think I'll go with the virtual functions, but just to clarify, if I declare a static variable with the same name in a derived class, it will basically override the base class right? So I can count on its existance in all derived classes...
-
Johannes Schaub - litb almost 15 yearsThere is no template called
Derived
. Instead, in this case, it'stemplate<typename> struct Base { static int staticVar; protected: ~Base() { } }; template<typename D> int Base<D>::staticVar; struct DerivedA : Base<DerivedA> { }; struct DerivedB : Base<DerivedB> { };
. Now there are two static variables, which you can access withDerivedB::staticVar
andDerivedA::staticVar
-
Greg Hewgill almost 15 yearsYou can in fact declare a static variable with the same name in a derived class. If you do this, I would qualify each reference to that variable with its class name, ie:
virtual int &staticVar() { return Derived::staticVarInst; }
-
S. Paris almost 8 yearsCRTP not really involved in there, it is more the specialization of the base class; could work with anything like Base<tag_type0> and Base<tag_type1>. But good thing to plug in the discussion the CRTP for those who do not know it ;)
-
Danger Code master over 7 yearsThis is indeed the CRTP (see en.wikipedia.org/wiki/Curiously_recurring_template_pattern); inheriting from a templated base class with your own class name as the argument is the definition of CRTP.
-
Daniel Duque over 5 yearsI know that I a am very late to the discussion, but it may help fellow googlers that are learning just like myself. Can anybody point the advantages/disadvanteges between this answer and the accepted answer?
-
Pellekrino about 5 yearsAccepted answer requires you to declare a new static variable and the access methods. This answer is more elegant : you write only once and get as many static variable as you need : one per template specialization.