所有的C++编译器都允许将静态常量整型类成员变量用作数组边界吗?

9

在VC++中,当我需要为类成员变量指定数组边界时,我是这样做的:

 class Class {

 private:
     static const int numberOfColors = 16;
     COLORREF colors[numberOfColors];
 };

(请不要告诉我在这里使用std::vector)

通过这种方式,我有一个常数可以用作数组边界,并且稍后在类代码中用于指定循环语句的约束条件,同时它不会在其他任何地方可见。

问题是,static const int成员变量的这种用法只允许VC++使用,还是其他广泛使用的编译器也允许?


8
“请不要告诉我在这里使用std::vector”,不,那并不合适。你应该使用std::tr1::array:) - sbi
9个回答

14

这是有效的C++代码,现代编译器(大部分或全部?)都支持它。如果你在使用Boost库,你可以通过BOOST_STATIC_CONSTANT宏来获得对该特性的可移植支持:

class Class {
 private:
     BOOST_STATIC_CONSTANT(int, numberOfColors = 16);
     COLORREF colors[numberOfColors];
 };

如果编译器支持,该宏将展开为static const int numberOfColors = 16,否则它将退而采用enum { numberOfColors=16 };


13

根据C++标准,该行为是合法的。任何现代编译器 应该 支持它。


7

我相信Visual Studio 2005及以上版本支持它。XCode C++编译器也是支持的(实际上这是gcc)。

如果你想要更加安全,你可以使用我从Effective C++中学到的旧枚举类型方法。方法如下:

class Class {

 private:
     enum {
        numberOfColors = 16
     };
     COLORREF colors[numberOfColors];
 };

希望这能有所帮助。

如果你正在处理 C++ 代码,那么枚举 'hack' 应该是不必要的,但如果你想让声明在 C 或 VC++6 中工作,我认为这比使用 #define 的常见方法更好。 - Michael Burr

6
这已经是标准C++超过十年的时间了。甚至VC也支持它,你还能想要什么?(@Neil: SunCC怎么样?:^>)

4
是的,它是100%合法的并且应该是可移植的。C++标准在5.19 - 常量表达式中这样说(重点在于“我的”):

In several places, C++ requires expressions that evaluate to an integral or enumeration constant: as array bounds (8.3.4, 5.3.4), as case-expressions (6.4.2), as bit-field lengths (9.6), as enumerator initializers (7.2), as static member initializers (9.4.2), and as integral or enumeration non-type template arguments (14.3).

constant-expression:
    conditional-expression

An integral constant-expression can involve only literals (2.13), enumerators, const variables or static data members of integral or enumeration types initialized with constant expressions (8.5), non-type template parameters of integral or enumeration types, and sizeof expressions.

话虽如此,看起来VC6不支持它。请查看StackedCrooked的回答获取一个很好的解决方法。实际上,对于这种情况,我通常更喜欢StackedCrooked提到的枚举方法。

顺便说一下,“static const”技术在VC9、GCC 3.4.5(MinGW)、Comeau和Digital Mars中都可以使用。

而且不要忘记,如果您使用“static const”成员,则严格来说需要除声明外还需要定义。然而,在这种情况下,几乎所有编译器都会让您省略定义。


3
除了其他答案,您可以使用以下函数来确定静态分配数组中的元素数量:
template<typename T, size_t length>
size_t arrayLength(T (&a)[length])
{
    return length;
}

2

我很确定这也适用于gcc和Solaris,但目前无法验证。

将来您可以像这样扩展这个想法:

template<int size>
class Class {
private:
    COLORREF colors[size];
};

并且像这样使用它:

Class<5> c;

这样您的应用程序就不会被限制在一个缓冲区大小上。


你正在使用一个魔数,而这正是问题所在。 - anon
@Neil:然而,上面的魔数5可以被一个static const int替换,这个常量可以来自于一个类,而‘c’可能会成为该类的成员。 - quamrana

1

我很久之前就不再担心那个问题的可移植性了。可能还有一些编译器不支持它,但是最近我没有遇到过。


-1

可以通过参考 ISO C++ 规范来回答这样的问题,但规范很难获取且更难阅读。我认为最简单的答案取决于两个方面:

  • Microsoft Visual Studio 2005 及以上版本是相对符合 C++ 实现的。如果它允许您做某事,则很有可能是标准的。
  • 下载类似 Code::Blocks 的东西以获取 GCC 编译器来尝试一些东西。如果在 MS 和 GCC 中都可以工作,那么很有可能是标准的。

规范很容易获取(售价30美元):https://dev59.com/wnVD5IYBdhLWcg3wHnyd#83763 阅读规范则是另一回事,但严肃的C++程序员应该时不时地参考它:https://dev59.com/7UjSa4cB1Zd3GeqPFGl7 - Michael Burr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接