静态全局变量V 静态全局类变量

3

声明字符串常量的方式,哪种更受推荐?

  1. 在文件范围内声明全局变量。
  2. 将其声明为类的全局变量。

该变量仅在类成员函数中使用。我倾向于认为第2种更好,因为它只与类成员函数相关。

A.cpp
---------------------
static const std::string hello_str = "Hello";

void A::print()
{
    std::cout << hello_str;
}

(或者)

A.h
---------------------
class A{
public:
    static const std::string hello_str;
    void print();
}

A.cpp
---------------------
const std::string A::hello_str = "Hello";

void A::print()
{
    std::cout << A::hello_str;
}

编辑 -1:

请允许我说,hello_str的内容可能会发生变化。例如,当开发者更改文件时,该字符串将手动更新。

在这种情况下,保持变量初始化在函数内是否有意义?用户更新字符串可能不太清晰 / 明显。如果将其保留为文件(1)或类(2)全局,则其他开发人员可以“识别”并修改此字符串。

鉴于上述用例,您仍然建议使用函数返回字符串吗?或者我可以使用具有私有访问说明符的类级静态变量?

2个回答

4

匿名命名空间是另一个选项:

A.cpp

namespace {
  const std::string hello_str("Hello");
}

void A::print() {
    std::cout << hello_str;
}

但你应该将其包装在一个函数中以进行延迟初始化。

那应该写成这样:

A.h
---------------------
class A{
public:
    static const std::string& hello_str();
    void print();
}

A.cpp
---------------------
const std::string& A::hello_str() {
  static const std::string str("Hello"); // << constructed on first call of A::hello_str()
  return str;
}

void A::print() {
    std::cout << A::hello_str();
}

在这种情况下,你也可以简单地通过值返回,避免使用静态/全局变量。你的std c++库实现可能使用所谓的“小字符串优化” ——如果是这样,创建或移动这么短的字符串将不需要堆分配。
同时注意,你提供的两个示例并不相同;其中一个实际上是私有的,另一个是公开可见的。
最终,你都不应该使用你提出的任何一种方法。考虑在函数内使用静态变量进行惰性初始化,或者(在许多情况下更好)通过值返回。
回答你最初的问题:我更喜欢在类内声明,但是声明为私有的。我发现这样更容易维护,可以应对实现的变化。当然,如果那个cpp文件中的静态变量以某种方式可以被外部实现访问,那么你可能还想在类内将其声明为私有的,以防止其他人访问它。

请问您能解释一下“一个实际上是私有的,而另一个是公开可见的”吗?- 我还以为1和2都是公开的。“我倾向于在类内部进行声明,但是设置为私有。”- 我理解这一部分,只有成员函数才能访问它,而不是从主函数(其他类的成员函数)中访问。“我发现这样更容易维护,因为实现可能会移动。当然,如果 CPP 中的 static 某种方式可以被外部实现访问,那么您可能也想将其在类内部声明为私有,以便其他人无法访问它。”- 请问您能解释这一点并/或为我提供一个示例吗? - Kingkong Jnr
1
@KingkongJnr 这只是显而易见的情况:在#1中,static可以被A.cpp中任何不在其之前的内容访问。如果A.cpp仅包含类A的定义,则它就是我所说的“有效私有”。静态变量的可见性和访问受到限制。这是C程序员用来保护他们的私有函数/数据的常用方法。例如:除非main()在A.cpp中定义,否则无法访问该静态变量。 - justin
@KingkongJnr 在这里,print 被声明为 private,而 foo 是公共的:class A { \n public: void foo(); \n private: \n void print(); \n }; - justin

2

简单规则:

  • string 逻辑上属于类,因此应该是一个类成员。
  • 类的所有实例共享相同的字符串,因此它属于类而不是特定的类实例(所有实例共享同一字符串),因此将其作为static成员。

这样做的好处是:

  • 只有需要访问字符串的类成员才能访问它,与声明为全局字符串不同。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接