Are static variables in a base class shared by all derived classes?

54,548

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 :(.

Share:
54,548
mpen
Author by

mpen

Updated on July 06, 2020

Comments

  • mpen
    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 and DerivedB share the same staticVar or will they each get their own?

    If I wanted them to each have their own, what would you recommend I do?

  • mpen
    mpen almost 15 years
    In 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
    mpen almost 15 years
    I 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
    Johannes Schaub - litb almost 15 years
    There is no template called Derived. Instead, in this case, it's template<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 with DerivedB::staticVar and DerivedA::staticVar
  • Greg Hewgill
    Greg Hewgill almost 15 years
    You 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
    S. Paris almost 8 years
    CRTP 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
    Danger Code master over 7 years
    This 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
    Daniel Duque over 5 years
    I 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
    Pellekrino about 5 years
    Accepted 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.