静态常量字符串(类成员)

时间:2009-10-14 02:00:24

标签: c++ string class static const

我想为一个类设置一个私有静态常量(在本例中是一个形状工厂)。

我想要有类似的东西。

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

不幸的是,我从C ++(g ++)编译器中得到了各种错误,例如:

  

ISO C ++禁止初始化   成员'RECTANGLE'

     

非整数类型'std :: string'

的静态数据成员的类内初始化无效      

错误:使'RECTANGLE'静止

这告诉我这种会员设计不符合标准。如何在不必使用#define指令的情况下拥有私有文字常量(或者可能是公共的)(我想避免数据全局性的丑陋!)

感谢任何帮助。

10 个答案:

答案 0 :(得分:434)

您必须在类定义之外定义静态成员,并在那里提供初始化程序。

第一

// 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";
};

无需其他定义。

答案 1 :(得分:143)

在C ++ 11中,你现在可以做到:

class A {
 private:
  static constexpr const char* STRING = "some useful string constant";
};

答案 2 :(得分:32)

在类定义中,您只能声明静态成员。它们必须在类之外定义。对于编译时积分常量,标准会使您可以“初始化”成员。但它仍然不是一个定义。例如,如果没有定义,取地址是行不通的。

我想提一下,我没有看到使用std :: string而不是const char [] 来获取常量的好处。 std :: string很好,除了它需要动态初始化。所以,如果你写了像

这样的东西
const std::string foo = "hello";

在命名空间范围内,foo的构造函数将在执行main启动之前运行,此构造函数将在堆内存中创建常量“hello”的副本。除非你真的需要RECTANGLE成为std :: string,否则你也可以写

// class definition with incomplete static member could be in a header file
class A {
    static const char RECTANGLE[];
};

// this needs to be placed in a single translation unit only
const char A::RECTANGLE[] = "rectangle";

有!没有堆分配,没有复制,没有动态初始化。

干杯,s。

答案 3 :(得分:16)

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

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

        return str;
    }
};

虽然我怀疑这是推荐的。

答案 4 :(得分:11)

在C ++ 17中,您可以使用内联变量

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

请注意,这与abyss.7's answer不同:此对象定义了实际的std::string对象,而不是const char*

答案 5 :(得分:7)

  

使用该类初始化   语法,常量必须是静态的   const的整数或枚举类型   通过常量表达式初始化。

这是限制。因此,在这种情况下,您需要在类外定义变量。请参阅@AndreyT的回答

答案 6 :(得分:4)

当前标准仅允许静态常量积分类型的初始化。所以你需要像AndreyT解释的那样做。但是,这将通过new member initialization syntax在下一个标准中提供。

答案 7 :(得分:4)

可能只做:

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

#define RECTANGLE "rectangle"

答案 8 :(得分:4)

你可以选择上面提到的const char*解决方案,但是如果你一直需要字符串,你将会有很多开销。
另一方面,静态字符串需要动态初始化,因此如果要在另一个全局/静态变量初始化期间使用其值,可能会遇到初始化顺序问题。为了避免这种情况,最便宜的是通过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_initializedmain()之前初始化,所以即使在多线程环境中也不需要锁定。默认情况下A_s_initialized为0(在动态初始化之前),因此如果在初始化s之前使用getS(),则可以安全地调用init函数。

顺便说一下,在上面的答案中:“ static const std :: string RECTANGLE()const ”,静态函数不能是const,因为它们无论如何都无法改变状态(没有这个指针)。

答案 9 :(得分:1)

快进到2018年和C ++ 17。

  • 请勿使用std :: string,而应使用std :: string_view文字
  • 请注意“ constexpr”波纹管。这也是一种“编译时”机制。
  • 没有内联并不意味着重复
  • 不需要任何cpp文件
  • static_assert仅在编译时有效

    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 ++