等效于 Java 静态对象类C++

Equivalent in C++ of Java static class of objects

本文关键字:对象 C++ 静态 Java      更新时间:2023-10-16

来自Java背景,我习惯于创建一个类A的概念,然后创建类B来保存类A的特定静态实例,以便在整个程序中使用。一些示例 Java 代码:

public class Color {
public int r;
public int g;
public int b;
public Color(int r, int g, int b) {
this.r = r;
this.g = g;
this.b = b;
}
}
public class Colors {
public static final Color WHITE = new Color(255, 255, 255);
public static final Color BLACK = new Color(0, 0, 0);
}

我尝试了一个class Color,带有一个名为colorsstruct Colors,但是我收到链接器错误,因为它在我包含它的每个文件中都会重新实例化colors。在C++做到这一点的最佳方法是什么?还是我试图以错误的方式解决问题?

假设你的问题实际上是你呈现的颜色问题,这可能是实现它的最简单方法:

struct Color
{
int r, g, b;
Color(int r, int g, int b)
{
this->r = r;
this->g = g;
this->b = b;
}
static Color WHITE() { return {255, 255, 255}; }
static Color BLACK() { return {0, 0, 0}; }
};

https://godbolt.org/g/DBrM1C


如果您出于某种原因需要能够引用静态对象(即每个命名颜色应该只有一个静态对象实例),您可以在标头中声明它们(Colors.h)并在关联的编译单元中初始化它们(Colors.cpp),但这有点麻烦,也意味着编译器无法内联/常量折叠等(至少没有链接时间优化)。如果常量发生变化,它确实可以保护您免受包含Colors.h的文件的重新编译。


这种方法将是一个(不是更好)中间地带,每种颜色仍然有一个静态对象实例,但您可以将其保留在标题中:https://godbolt.org/g/13krNc

但请注意,尽管进行了优化,但编译器无法确定bar()应始终返回255。相反,它必须在每次调用中检查静态常量是否已初始化,如果没有,则初始化它们(这需要锁定线程安全!

在C++中,包含是实际的包含。这意味着,与Java导入相比,代码实际上是复制的

现在,当您多次包含文件时,您的代码将多次出现。这就是为什么您需要保护您的标头代码不被复制两次。

解决方案 1:将以下内容作为头文件的第一行写入:

#pragma once

解决方案 2(更便携且广泛推荐):

#ifndef MYHEADERFILENAME_H
#define MYHEADERFILENAME_H
// your header code goes here
#endif /* MYHEADERFILENAME_H */

关于您的问题的更多想法:

  1. 不要使用类来封装 constexpr 值。这在C++中不是必需的。在Java中,类之外不能有东西,但在C++中,这是完全合法的。只需声明您的符号并在类之外的源文件中定义它。但是,您应该在自己的命名空间中声明它,以避免名称冲突。

  2. 也许枚举类(又名作用域枚举)更接近您真正想要的。