我想有一个类的私有静态常量(在这种情况下是一个形状工厂)。

我想要这样的东西。

class A {
   private:
      static const string RECTANGLE = "rectangle";
}

不幸的是,我从c++ (g++)编译器得到了各种各样的错误,比如:

ISO c++禁止初始化 “矩形”成员 非整型静态数据成员' std::string '的类内初始化无效 错误:使“矩形”静态

这说明这种构件设计是不符合标准的。如何在不使用#define指令的情况下获得私有文字常量(或者公共常量)(我想避免数据全局的丑陋!)

任何帮助都是感激的。


当前回答

使用类内初始化 语法中,常量必须是静态的 整型或枚举类型的常量 由常量表达式初始化。

这就是限制条件。因此,在这种情况下,您需要在类之外定义变量。引用@AndreyT的答案

其他回答

使用类内初始化 语法中,常量必须是静态的 整型或枚举类型的常量 由常量表达式初始化。

这就是限制条件。因此,在这种情况下,您需要在类之外定义变量。引用@AndreyT的答案

当前标准只允许对静态常量整型进行这样的初始化。所以你需要按照AndreyT解释的去做。但是,这将在下一个标准中通过新的成员初始化语法实现。

可能的只是做:

static const std::string RECTANGLE() const {
    return "rectangle";
} 

or

#define RECTANGLE "rectangle"

在c++ 17中,你可以使用内联变量:

class A {
 private:
  static inline const std::string my_string = "some useful string constant";
};

注意,这与深渊不同。7的回答:它定义了一个真正的std::string对象,而不是const char*

类静态变量可以在头文件中声明,但必须在.cpp文件中定义。这是因为一个静态变量只能有一个实例,而编译器无法决定将它放在哪个生成的对象文件中,所以你必须做出决定。

将静态值的定义与c++ 11中的声明保持一致 可以使用嵌套的静态结构。在本例中是static成员 是一个结构,必须在.cpp文件中定义,但值 都在头文件中。

class A
{
private:
  static struct _Shapes {
     const std::string RECTANGLE {"rectangle"};
     const std::string CIRCLE {"circle"};
  } shape;
};

不是初始化单个成员,而是在.cpp中初始化整个静态结构:

A::_Shapes A::shape;

访问这些值

A::shape.RECTANGLE;

或者——因为成员是私有的,只能从A - with中使用

shape.RECTANGLE;

注意,这个解决方案仍然受到的顺序问题的影响 静态变量的初始化。当使用静态值时 初始化另一个静态变量,第一个可能没有初始化, 然而。

// file.h
class File {
public:
  static struct _Extensions {
    const std::string h{ ".h" };
    const std::string hpp{ ".hpp" };
    const std::string c{ ".c" };
    const std::string cpp{ ".cpp" };
  } extension;
};

// file.cpp
File::_Extensions File::extension;

// module.cpp
static std::set<std::string> headers{ File::extension.h, File::extension.hpp };

在这种情况下,静态变量头将包含{""} 或{".h", ".hpp"},这取决于链接器创建的初始化顺序。

正如@abyss提到的。7如果变量的值可以在编译时计算,你也可以使用constexpr。但是如果你用静态constexpr const char*声明你的字符串,并且你的程序使用std::string,否则就会有开销,因为每次你使用这样的常量都会创建一个新的std::string对象:

class A {
public:
   static constexpr const char* STRING = "some value";
};
void foo(const std::string& bar);
int main() {
   foo(A::STRING); // a new std::string is constructed and destroyed.
}