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

我想要这样的东西。

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

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

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

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

任何帮助都是感激的。


当前回答

这只是额外的信息,但如果你真的想在头文件中使用字符串,可以尝试如下方法:

class foo
{
public:
    static const std::string& RECTANGLE(void)
    {
        static const std::string str = "rectangle";

        return str;
    }
};

尽管我怀疑这是否被推荐。

其他回答

你必须在类定义之外定义你的静态成员,并在那里提供初始化式。

第一个

// In a header file (if it is in a header file in your case)
class A {   
private:      
  static const string RECTANGLE;
};

然后

// In one of the implementation files
const string A::RECTANGLE = "rectangle";

您最初尝试使用的语法(类定义中的初始化式)只允许整型和枚举类型。


从c++ 17开始,你有另一个选项,这与你最初的声明非常相似:内联变量

// In a header file (if it is in a header file in your case)
class A {   
private:      
  inline static const string RECTANGLE = "rectangle";
};

不需要额外的定义。

快进到2018年和c++ 17。

do not use std::string, use std::string_view literals please do notice the 'constexpr' bellow. This is also an "compile time" mechanism. no inline does not mean repetition no cpp files are not necessary for this static_assert 'works' at compile time only using namespace std::literals; namespace STANDARD { constexpr inline auto compiletime_static_string_view_constant() { // make and return string view literal // will stay the same for the whole application lifetime // will exhibit standard and expected interface // will be usable at both // runtime and compile time // by value semantics implemented for you auto when_needed_ = "compile time"sv; return when_needed_ ; } };

以上是一个适当的、合法的标准c++公民。它可以很容易地涉及到任何和所有std::算法、容器、实用程序等。例如:

// test the resilience
auto return_by_val = []() {
    auto return_by_val = []() {
        auto return_by_val = []() {
            auto return_by_val = []() {
return STANDARD::compiletime_static_string_view_constant();
            };
            return return_by_val();
        };
        return return_by_val();
    };
    return return_by_val();
};

// actually a run time 
_ASSERTE(return_by_val() == "compile time");

// compile time 
static_assert(
   STANDARD::compiletime_static_string_view_constant() 
   == "compile time" 
 );

享受标准c++吧

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

可能的只是做:

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

or

#define RECTANGLE "rectangle"

你可以使用上面提到的const char*解决方案,但是如果你总是需要字符串,你将会有很多开销。 另一方面,静态字符串需要动态初始化,因此如果你想在另一个全局/静态变量初始化期间使用它的值,你可能会遇到初始化顺序的问题。为了避免这种情况,最便宜的方法是通过getter访问静态字符串对象,getter检查对象是否已初始化。

//in a header  
class A{  
  static string s;   
public:   
  static string getS();  
};  
//in implementation  
string A::s;  
namespace{  
  bool init_A_s(){  
    A::s = string("foo");   
    return true;  
  }  
  bool A_s_initialized = init_A_s();  
}  
string A::getS(){      
  if (!A_s_initialized)  
    A_s_initialized = init_A_s();  
  return s;  
}  

记住只使用A::getS()。因为任何线程只能由main()启动,并且A_s_initialized在main()之前初始化,所以即使在多线程环境中也不需要锁。默认情况下A_s_initialized为0(在动态初始化之前),因此如果在s初始化之前使用getS(),则可以安全地调用init函数。

顺便说一句,在上面的答案:“static const std::string RECTANGLE() const”,静态函数不能是const,因为它们不能改变任何对象的状态(没有this指针)。