等效于 Java 静态对象类C++
Equivalent in C++ of Java static class of objects
来自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
,带有一个名为colors
的struct 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 */
关于您的问题的更多想法:
不要使用类来封装 constexpr 值。这在C++中不是必需的。在Java中,类之外不能有东西,但在C++中,这是完全合法的。只需声明您的符号并在类之外的源文件中定义它。但是,您应该在自己的命名空间中声明它,以避免名称冲突。
也许枚举类(又名作用域枚举)更接近您真正想要的。
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- CMake-按正确顺序将项目与C运行时对象文件链接
- 空基优化子对象的地址
- 将对象数组的引用传递给函数
- 你能重载对象变量名本身返回的内容吗
- C++使用整数的压缩数组初始化对象
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 将对象移动到std::shared_ptr
- 代理对象的常量正确性
- 提升 ASIO 无法识别计时器对象
- 将Ref对象作为类成员
- 将包含C样式数组的对象初始化为成员变量(C++)
- 如何返回一个类的两个对象相加的结果
- 使用std::函数映射对象方法
- 是否需要删除包含对象的"pair"?
- 如何在自删除后将对象设置为nullptr
- 迭代时从向量和内存中删除对象
- 构造对象的歧义
- 使用"std::unordereded_map"映射到"std::list"对象