为什么本地类中的字段不能是静态的?

时间:2011-05-26 10:48:53

标签: c++ static-members local-class

void foo (int x)
{
  struct A { static const int d = 0; }; // error
}

除了标准的引用之外,是否有任何动机可以禁止内部类中的static字段?

error: field `foo(int)::A::d' in local class cannot be static

修改:但是,允许使用static个成员函数。对于这种情况,我有一个用例。假设我只想为POD调用foo(),那么我可以像

那样实现它
template<typename T>
void foo (T x)
{
  struct A { static const T d = 0; }; // many compilers allow double, float etc.
}

foo()应该只传递POD(如果允许static)而不传递给其他数据类型。这只是我脑海中的一个用例。

6 个答案:

答案 0 :(得分:5)

Magnus Skog给出了真正的答案:静态数据成员只是一个声明;该对象必须在其他地方定义,在命名空间范围内,并且类定义在命名空间范围内不可见。

请注意,此限制仅适用于静态数据成员。这意味着有一个简单的解决方法:

class Local
{
    static int& static_i()
    {
        static int value;
        return value;
    }
};

这为您提供了完全相同的功能,但代价是 使用函数语法来访问它。

答案 1 :(得分:4)

我想这是因为必须在全局范围内定义静态类成员。

编辑:

对不起是一个懒鬼,只是丢掉东西:)更准确一点。需要在全局范围内定义类的静态成员,例如

foo.h中

class A {
  static int dude;
};

Foo.cpp中

int A::dude = 314;

现在,由于void foo(int x)中的作用域不是全局的,因此没有用于定义静态成员的作用域。希望这更清楚一点。

答案 2 :(得分:4)

因为没有人认为有任何需要吗?

[edit] :静态变量只需要定义一次,通常在类之外(内置函数除外)。在本地类中允许它们也需要设计一种定义它们的方法。的 [/编辑]

添加到某种语言的任何功能都有费用:

  • 必须由编译器实现
  • 必须在编译器中维护(并且可能会引入错误,即使在其他功能中也是如此)
  • 它存在于编译器中(因此即使在未使用时也可能导致某些速度减慢)

有时,未实施功能是正确的决定。

本地函数和类会给语言增加难度,但收效甚微:使用static函数和未命名的命名空间可以避免使用它们。

坦率地说,如果我必须做出决定,我会完全删除它们:它们只会使语法混乱。

一个例子:The Most Vexing Parse

答案 3 :(得分:0)

我认为这是同样的命名问题阻止我们在模板实例化中使用本地类型。

名称foo()::A::d不是链接器要解析的好名称,那么它应该如何找到静态成员的定义?如果函数baz()中有另一个结构A怎么办?

答案 4 :(得分:0)

有趣的问题,但我很难理解你为什么想要本地班级的静态成员。静态通常用于维护程序流的状态,但在这种情况下使用范围为foo()的静态变量不是更好吗?

如果我不得不猜测为什么存在限制,我会说这与编译器知道何时执行静态初始化的难度有关。 C ++标准文档可能提供更正式的理由。

答案 5 :(得分:0)

只是因为。

关于C ++的一件令人讨厌的事情是,它对“全局上下文”概念有很强的依赖性,在此概念中,所有事物都必须唯一地命名。甚至嵌套的名称空间机制也只是字符串欺骗。

我想(只是一个疯狂的猜测)一个严重的技术问题正在与为C设计的链接器一起使用,并且进行了一些调整才能使其与C ++一起使用(并且C ++代码需要C互操作性)。

能够获得任何C ++代码并“包装”它以便能够在一个较大的项目中使用而不会发生冲突是很好的,但是由于链接问题,情况并非如此。我认为在功能级别上禁止使用静态方法或非内联方法(甚至是嵌套函数)没有任何合理的哲学理由,但这是我们目前所得到的。

即使声明/定义对偶及其所有烦人的冗长性和含义也与实现问题有关(并且可以在不提供源代码的情况下提供出售可用的目标代码的能力,但由于良好的原因,这种情况现在不那么受欢迎了)。