【问题标题】:Idiom for a C++11 enum with methods and static instances?带有方法和静态实例的 C++11 枚举的成语?
【发布时间】:2020-08-16 18:45:34
【问题描述】:

我想执行以下操作(不会编译):

class Foo {
    int value;

    Foo(const int arg)
        : value{arg}
    {}

public:    
    static const Foo a{0};
    static const Foo b{1};
    static const Foo c{2};

    Foo func(const Foo& foo) {...}
};

这样Foo 的实例受到严格控制(就像在enum 中一样),这样我就可以编写像auto foo = Foo::a;auto foo = Foo::a.func(Foo::b); 这样的代码

很遗憾,由于静态实例的类型不完整,因此代码无法在 C++11 下编译。

这个有成语吗?

【问题讨论】:

  • 在 C++11 中 static 成员必须单独定义。在您的班级 static const Foo b; 中,在您的 .cpp Foo const Foo::b = 1; 中。或者,C++17 为 inline 添加了一个新含义,让您可以在 class 中编写 static inline const Foo b{1};,而无需单独定义。
  • 这是不可能的,你不能创建一个类的实例(一个对象),直到类被完全定义(它是与关闭})。也许如果你解释你试图用这个解决的实际问题,并解释为什么你不能使用枚举(“经典”或 C++11 强类型变体),我们也许可以帮你解决这个问题?

标签: c++ c++11 enums


【解决方案1】:

您可以很容易地做到这一点,但您需要将常量的定义放在类之外:

class Foo {
    int value;

    // In C++17, you could make this constexpr.
    Foo(const int arg)
        : value{arg}
    {}

public:
    // in C++20, you could make these constinit.
    static const Foo a;
    static const Foo b;
    static const Foo c;
};

// In C++11 these need to go in the source file to avoid linker errors.
// In C++17 you could make them inline and put them in the header.
// In C++20 you could make them constinit.
const Foo Foo::a = 0;
const Foo Foo::b = 1;
const Foo Foo::c = 2;

不过,我不会称这是一个优雅的解决方案。特别是在 C++11 中,这些常量不能被编译器内联,因为它们需要进入源文件。这会对性能产生重大影响。因此,如果您要这样做,我建议您至少使用 C++17,如果不是 C++20。

通常,C++ 枚举是整数常量,不支持像 Java 中那样获取 enum 的序数或名称。另一种方法是使用没有值的enum class(默认值为 0、1、2、...),然后将它们用作查找表中的索引。

对属性使用switch 也可以解决问题:

enum class Axis : unsigned { X, Y, Z };

// in C++17, you could make this constexpr.
inline const char *nameOf(Axis axis)
{
    switch (axis) {
    case Axis::X: return "X";
    case Axis::Y: return "Y";
    case Axis::Z: return "Z";
    }
}

【讨论】:

    猜你喜欢
    • 2012-07-10
    • 1970-01-01
    • 1970-01-01
    • 2012-10-09
    • 2015-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多