14
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允许成员函数。对于这种情况,我有一个用例。假设我只想foo()为 POD 调用,那么我可以像这样实现它,

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

foo()应该只通过 POD(如果static允许)而不是其他数据类型。这只是我想到的一个用例。

4

6 回答 6

5

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

编辑:

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

foo.h

class A {
  static int dude;
};

foo.cpp

int A::dude = 314;

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

于 2011-05-26T10:52:39.227 回答
5

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

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

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

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

于 2011-05-26T13:13:11.367 回答
4

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

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

任何添加到语言的功能都是有代价的:

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

有时,不实现某个功能是正确的决定。

本地函数和类已经给语言增加了难度,但收获甚微:它们可以通过static函数和未命名的命名空间来避免。

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

一个例子:The Most Vexing Parse

于 2011-05-26T12:12:26.120 回答
0

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

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

于 2011-05-26T11:07:43.377 回答
0

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

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

于 2011-05-26T12:07:35.110 回答
0

只是因为。

关于 C++ 的一个令人讨厌的事情是,它强烈依赖于“全局上下文”概念,其中所有内容都必须唯一命名。即使是嵌套的命名空间机制也只是字符串诡计。

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

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

即使是声明/定义的二元性及其所有令人讨厌的冗长和含义也只是关于实现问题(并且提供了在不提供源代码的情况下出售可用目标代码的能力,由于充分的理由,现在已经不那么流行了)。

于 2020-07-01T08:48:20.507 回答