C++ 基类中的静态变量是否由所有派生类共享?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1390913/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Are static variables in a base class shared by all derived classes?
提问by mpen
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?
都将DerivedA
与DerivedB
共享相同的staticVar
或者他们每人将获得自己?
If I wanted them to each have their own, what would you recommend I do?
如果我想让他们每个人都有自己的,你会推荐我做什么?
采纳答案by Greg Hewgill
They will each share the same instance of staticVar
.
它们将共享相同的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();
回答by Mark Ingram
To ensure that each class has its own static variable, you should use the "Curiously recurring template pattern" (CRTP).
为了确保每个类都有自己的静态变量,您应该使用“Curously 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> {};
回答by Alan
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.
编辑:一个可能的解决方案是将您的基类定义为模板。在此模板中定义静态变量意味着每个派生类都将拥有自己的静态变量实例。
回答by Reed Copsey
There is only one staticVar
in your case: Base::staticVar
staticVar
你的情况只有一个: 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.
当你在一个类中声明一个静态变量时,这个变量是为那个类单独声明的。在您的情况下, DerivedA 甚至看不到staticVar
(因为它是私有的,不受保护或公共的),因此它甚至不知道存在staticVar
变量。
回答by milembar
The sample code given by @einpoklum is not working as it is because of the missing initialization of the static member foo_
, missing inheritance in FooHolder
declaration, and missing public
keywords since we are dealing with classes. Here is the fixed version of it.
@einpoklum 给出的示例代码无法正常工作,因为缺少静态成员的初始化、声明中foo_
缺少继承FooHolder
以及public
由于我们正在处理类而缺少关键字。这是它的固定版本。
#include <iostream>
#include <string>
class A {
public:
virtual const int& Foo() const = 0;
};
template <typename T>
class FooHolder : public virtual A {
public:
const int& Foo() const override { return foo_; }
static int foo_;
};
class B : public virtual A, public FooHolder<B> { };
class C : public virtual A, public FooHolder<C> { };
template<>
int FooHolder<B>::foo_(0);
template<>
int FooHolder<C>::foo_(0);
int main()
{
B b;
C c;
std::cout << b.Foo() << std::endl;
std::cout << c.Foo() << std::endl;
}
回答by einpoklum
Alas, C++ has no virtual static data members. There are several ways to simulate this, more or less:
唉,C++ 没有虚拟静态数据成员。有几种方法可以或多或少地模拟这一点:
- @GregHewgill's solutionhas you replicate the static variable in each derived class; this solution is simple, straightforward and doesn't introduce additional classes, but I don't like this one since it's verbose, and you have to be rather disciplined with it.
- @MarkIngram suggested a CRTP-based solution, which saves you most of the typing; however, it messes up the inheritance structure, because what were previously subclasses of A are no longer really related as classes. After all, two templated types with the same name but different template arguments could be just any two types.
- @GregHewgill 的解决方案让您在每个派生类中复制静态变量;这个解决方案简单、直接并且不引入额外的类,但我不喜欢这个,因为它很冗长,而且你必须对它有相当的纪律。
- @MarkIngram 建议了一个基于 CRTP 的解决方案,它可以为您节省大部分打字时间;然而,它弄乱了继承结构,因为以前是 A 的子类的东西不再与类真正相关。毕竟,具有相同名称但不同模板参数的两个模板化类型可以是任意两种类型。
I suggest a different CRTP-based solution, using a mix-inclass:
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> { }
The only thing you need to do in a subclass is also indicate the mix-in inheritance. There might be some virtual inheritance caveats I'm missing here (as I rarely use it).
在子类中你唯一需要做的就是指明混合继承。可能有一些我在这里遗漏的虚拟继承警告(因为我很少使用它)。
Note that you either have to instantiate and initialize each subclass' static variable somewhere, or you can make it an inline
variable (C++17) and initialize it within the template.
请注意,您必须在某处实例化和初始化每个子类的静态变量,或者您可以将其设为inline
变量 (C++17) 并在模板中对其进行初始化。
This answer was adapted from my answer to a dupe question.
这个答案改编自我对一个欺骗性问题的回答。
回答by Francis Cugler
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
派生的Foos.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
派生的Foos.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 :(
.
如果__FUNCTION__
在您的构造函数中不适合您,那么您可以使用类似的东西来替换它,例如__PRETTY_FUNCTION__
或__func__
,或者手动输入每个类的名称:(
。