在由所有派生类共享基类的静态变量?(Are static variables in a base c

2019-07-05 12:42发布

如果我有这样的事情

class Base {
    static int staticVar;
}

class DerivedA : public Base {}
class DerivedB : public Base {}

都将DerivedADerivedB共享相同的staticVar或他们每人将获得自己?

如果我想他们各有各的,你会建议我做什么?

Answer 1:

他们将分享各自的同一个实例staticVar

为了让每一个派生类中获得自己的静态变量,你需要声明另一个静态变量使用不同的名称。

然后,您可以使用虚拟对函数在基类来获取和设置变量的值,并覆盖在每个派生类中的一对来获取和设置“本地”静态变量为类。 另外,您可以使用返回引用一个单一的功能:

class Base {
    static int staticVarInst;
public:
    virtual int &staticVar() { return staticVarInst; }
}
class Derived: public Base {
    static int derivedStaticVarInst;
public:
    virtual int &staticVar() { return derivedStaticVarInst; }
}

然后,您可以使用它作为:

staticVar() = 5;
cout << staticVar();


Answer 2:

为了确保每个类都有自己的静态变量,你应该使用“奇异递归模板模式”(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> {};


Answer 3:

他们将共享相同的实例。

你需要为每个子类中单独声明静态变量,或者你可以考虑在其中,你可以存储由派生类引用变量简单的静态地图。


编辑 :一个可能的解决方案,这将是定义你的基类为模板。 有了这个模板中定义的静态变量将意味着每个派生类都会有它自己的静态实例。



Answer 4:

只有一个staticVar ,你的情况: Base::staticVar

当你在一个类中声明静态变量,该变量单独声明该类。 在你的情况,DerivedA甚至不能看到staticVar (因为它是私有的,不受保护或公共),所以它甚至不知道有一个staticVar存在变量。



Answer 5:

可惜的是,C ++有没有虚拟静态数据成员。 有几种方法来模拟这一点,或多或少:

  • @ GregHewgill的解决方案具有您复制在每个派生类的静态变量; 该解决方案是简单,直接,不引入额外的课程,但因为它是冗长的,我不喜欢这个,你必须是相当有纪律它。
  • @MarkIngram提出了基于CRTP的解决方案 ,这样可以节省大部分打字; 然而,它搅乱了继承结构,因为什么以前A的子类不再是真正相关的课程。 毕竟两个模板类型名称相同,但不同的模板参数可能只是某两种。

我提出一个不同的CRTP为基础的解决方案,采用了混合式类:

 class A {
      virtual const int& Foo() const = 0;
 }

 template <typename T>
 class FooHolder {
      static int foo_;
      const int& Foo() const override { return foo_; }
 }

 class B : A, virtual FooHolder<B> { }

 class C : B, virtual FooHolder<B> { }

你需要在子类中做的唯一的事情也表明了混合式的继承。 可能有一些虚拟继承告诫我在这里失踪(因为我很少使用它)。

需要注意的是,你要么必须实例化和地方初始化每个子类静态变量,或者你可以把它的inline变量(C ++ 17)和模板中进行初始化。

这个答案是改编自我回答一个欺骗的问题 。



Answer 6:

我知道这个问题已经回答了,但我想提供静态成员继承的一个小例子。 这是证明的用处以及什么是用静态变量和各自的构造发生了一个非常好的方式。

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;
}

如果__FUNCTION__是不是在你的构造函数为你工作,那么你可以使用类似的东西可以取代它如__PRETTY_FUNCTION____func__ ,或手动键入出每个类的名称:(



文章来源: Are static variables in a base class shared by all derived classes?