相当于Java静态类对象的C ++

时间:2018-04-11 12:46:24

标签: c++

来自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 Colorstruct Colors名为colors但我收到了链接器错误,因为colors在我包含的每个文件中都会重新实现。在C ++中执行此操作的最佳方法是什么?或者我试图以错误的方式解决问题?

2 个答案:

答案 0 :(得分:0)

假设您的问题实际上是您提出的问题,这可能是实现它的最简单方法:

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。相反,它必须检查每次调用是否已经初始化静态常量,如果没有,则初始化它们(这需要锁定线程安全!)。

答案 1 :(得分:-2)

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

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

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

#pragma once

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

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

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

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

  2. 也许枚举类scoped enumeration更接近你真正想要的东西。