简体   繁体   English

如何在 C++ 中使用公共静态变量

[英]How to use public static variables in C++

There doesn't seem to be a clear, concise example of real word use of a public static variable in C++ from multiple files on StackOverflow.在 StackOverflow 上的多个文件中,似乎没有一个清晰、简洁的示例,说明在 C++ 中使用公共静态变量的真实单词。

There are many examples showing how to use static variables in a single C++ translation unit, and many questions about the precise nature of the various uses of the static keyword, but as a programmer more experienced with C# I found it hard to scrape together what I needed to simply "have a static variable on a class and use it elsewhere" like you would in C# or Java.有很多示例展示了如何在单个 C++ 翻译单元中使用静态变量,还有很多关于 static 关键字各种用法的确切性质的问题,但作为一名对 C# 更有经验的程序员,我发现很难将我的内容拼凑起来需要像在 C# 或 Java 中一样简单地“在类上有一个静态变量并在其他地方使用它”。

Here I will try to demonstrate what I discovered in the most straightforward way.在这里,我将尝试以最直接的方式展示我的发现。 I hope that others will then improve on the answer and give more technical details for those that are interested.我希望其他人随后会改进答案,并为感兴趣的人提供更多技术细节。

SomeClass.h某个类.h

In the header file for the class where we want to have a static variable, we just declare it static like we would in C# or Java.在我们想要拥有静态变量的类的头文件中,我们只需像在 C# 或 Java 中一样将其声明为静态。 Don't try to initialise the variable here;不要尝试在这里初始化变量; C++ doesn't like that. C++ 不喜欢那样。

class SomeClass
{
public:
  static bool some_flag;
};

SomeClass.cpp类.cpp

In the cpp file for the class, we create the storage for the static variable, just like we would provide the implementation for a member function.在类的 cpp 文件中,我们为静态变量创建存储,就像我们为成员函数提供实现一样。 Here we can initialise the variable.在这里我们可以初始化变量。 So far, this is going swimmingly!到目前为止,一切顺利!

#include "SomeClass.h"

bool SomeClass::some_flag = true;

SomeOtherClass.cpp其他类.cpp

Here is where I ran into problems.这是我遇到问题的地方。 If we try to just access SomeClass::some_flag from elsewhere (which, let's face it, is probably the reason you wanted a public static variable in the first place), the linker will complain that it doesn't know where it lives.如果我们尝试从其他地方访问SomeClass::some_flag (让我们面对SomeClass::some_flag ,这可能是您首先想要公共静态变量的原因),链接器会抱怨它不知道它所在的位置。 We've told the compiler that the static variable exists, so the compiler is happy.我们已经告诉编译器静态变量存在,所以编译器很高兴。 The problem is that in this other translation unit we've never specified where that static variable is stored.问题是在另一个翻译单元中,我们从未指定该静态变量的存储位置。 You may be tempted to try redeclaring the storage, and hoping the linker resolves them both as "the some_flag I declared in SomeClass.h ", but it won't.您可能会尝试重新声明存储,并希望链接器将它们都解析为“我在SomeClass.h声明的some_flag ”,但它不会。 It will complain that you've given the variable two homes, which of course is not what you meant.它会抱怨你给了可变的两个家,这当然不是你的意思。

What we need to do is to tell the linker that the storage for some_flag lives elsewhere, and that it will be found once we try to put all the translation units together at link time.我们需要做的是告诉链接器some_flag的存储some_flag其他地方,一旦我们尝试在链接时将所有翻译单元放在一起,就会找到它。 We use the extern keyword for this.为此,我们使用extern关键字。

#include "SomeOtherClass.h"
#include "SomeClass.h"

extern bool SomeClass::some_flag;

void SomeOtherClass::SomeOtherFunction()
{
  SomeClass::some_flag = true;
};

Voila!瞧! The compiler is happy, the linker is happy, and hopefully the programmer is also happy.编译器很高兴,链接器很高兴,希望程序员也很高兴。

I now leave this open for a discussion on how I should not have used a public variable, could have just passed an instance of SomeClass through the 87 layers of code that's between it and the usage, should have used some feature coming in C++23, should have used boost::obscurething etc. etc.我现在将这个开放讨论我不应该使用公共变量,本可以通过它和用法之间的 87 层代码传递SomeClass的实例,应该使用 C++ 中的一些功能23、应该使用boost::obscurething等等。

I do however welcome any alternative approaches to this fundamental problem that are true to the usage I've demonstrated here.但是,我确实欢迎针对这个基本问题的任何替代方法,这些方法适用于我在此处演示的用法。

Here is where I ran into problems.这是我遇到问题的地方。 If we try to just access SomeClass::some_flag from elsewhere [...], the linker will complain that it doesn't know where it lives.如果我们试图从其他地方访问 SomeClass::some_flag [...],链接器会抱怨它不知道它所在的位置。

The linker won't complain, as long as you link with the translation unit that defines the variable ( SomeClass.cpp ).只要您与定义变量 ( SomeClass.cpp ) 的翻译单元链接,链接器就不会抱怨。

 extern bool SomeClass::some_flag;

This declaration is neither allowed, nor is it necessary.这种声明既不允许,也没有必要。 The class definition that contains the variable declaration is sufficient for the compiler, and the variable definition in SomeClass.cpp is sufficient for the linker.包含变量声明的类定义对于编译器来说就足够了, SomeClass.cpp的变量定义对于链接器来说就足够了。 Demo演示

Don't try to initialise the variable here;不要尝试在这里初始化变量; C++ doesn't like that. C++ 不喜欢那样。

I do however welcome any alternative approaches to this fundamental problem然而,我确实欢迎解决这个基本问题的任何替代方法

You could simply use an inline variable (since C++17):您可以简单地使用内联变量(C++17 起):

class SomeClass
{
public:
    inline static bool some_flag = true;

The answer, in summary form, for people who just want the code so they can get back to work:对于只想要代码以便他们可以重新开始工作的人来说,答案是总结形式:

SomeClass.h某个类.h

#pragma once

class SomeClass
{
public:
  static bool some_flag;
};

SomeClass.cpp类.cpp

#include "SomeClass.h"

bool SomeClass::some_flag = true;

SomeOtherClass.cpp其他类.cpp

#include "SomeOtherClass.h"
#include "SomeClass.h"

extern bool SomeClass::some_flag;

void SomeOtherClass::SomeOtherFunction()
{
  SomeClass::some_flag = true;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM