为什么类的静态成员函数没有“常量正确性”概念?

11

使用案例:

class A {
  static int s_common;
public:
  static int getCommon () const { s_common; };
};

通常这会导致以下错误:

错误:静态成员函数“static int A::getCommon()”不能具有cv限定符

这是因为const只适用于this指向的对象,而在static成员函数中不存在this

然而,如果允许这样做,static成员函数的"const"属性可以很容易地与static数据成员相关联。
为什么C++没有这个特性?有没有逻辑上的原因?


1
@keety,那个问题是相关的,但不是重复的。我已经看过并点赞了它。我在我的问题中提到了this指针参数,但似乎这还不够。 - iammilind
很酷,但如果您在问题中链接原始线程以获得上下文,可能会更好,否则您可能会得到相同的答案。 - keety
6个回答

8

cv-qualifiers会影响函数的签名。所以你可以有以下这些:

class A {
  static int s_common;
public:
  static void getCommon () const {  };
  static void getCommon () {  };
};

现在...你会如何称呼这个“const”?没有“const”对象可以调用它(好吧,你可以在“const”对象上调用它,但那不是重点)。我只是猜测,可能还有其他原因。 :)

3
这样的组合可能被视为非法。我不确定这是否足以排除这种可能性。 - Michael Anderson
2
@MichaelAnderson 为什么会是非法的?标准规定可以通过cv限定符进行重载。如果我们改变规则,任何事情都可能被视为非法。 - Luchian Grigore
-1 @Luchian:允许使用“static const”的新规则将使重载无效,因为它除了通过强制转换外很难解决。这就是原因所在。因此,我认为你的答案被错误地选为解决方案:它根本不是一个理由,只是一种联想上的误解。 - Cheers and hth. - Alf
@Cheersandhth.-Alf 当然,你可以修改规则使任何事情无效。但这只是一个猜测(正如答案本身所指出的那样)。我认为,仅仅因为你能想到一种方式来改变规则使其无效,这并不意味着它是一个无效的答案。 - Luchian Grigore
非常好的观点,但正如你自己怀疑的那样,实际原因是不同的。这在Nicol Bolas和Alok Save的答案中已经给出了。 - Frank Puffer

8
然而,如果允许的话,静态成员函数的“const”属性可以轻松与静态数据成员相关联。这就是您的问题变得混乱的地方。声明为“const”的非静态成员函数仍然对静态数据成员具有非“const”访问权限。“const”仅适用于“this”(即非静态数据成员)。在语法上以相同方式使用“const”的静态成员函数具有完全不同的结果(即使得访问静态数据成员成为“const”)。此外,静态数据成员只是类范围全局变量,在其中具有类访问控制(public/private等)。因此,某些函数具有不同的“const”访问权限,特别是基于它们的签名,是没有意义的。

5
具有const cv-限定符的成员函数的原因是:
表示传递给成员函数的隐藏指针this是不可变的,不能被修改。静态成员函数没有隐藏的this参数,因此对于静态成员函数来说,const是没有意义的。 然而,如果允许,则可以轻松地将静态成员函数的“const”比较与静态数据成员相关联。 这不是添加const限定符的原始原因,这一点很明显,因为您无法将cv-限定符应用于自由函数。 cv-限定符仅用于调用函数的对象this

我也删掉了我的评论,因为没有你之前的评论就没有意义了。感觉无限循环要来了。:)) - Luchian Grigore
有趣的是,我一直认为const只是一种声明函数不会改变对象的方式。这意味着对于静态函数来说它是多余的(因为它没有对象),但我不明白为什么它会被禁止而不是只是被忽略。 - paxdiablo

2

一个不改变任何全局状态的函数是纯函数。C++11引入了属性,可能包括在特定平台上使用[[pure]]

const的一个问题是它是函数的一部分类型。将static const函数分配给“普通”函数指针需要特殊的转换、强制转换或衰减规则。正如Luchian所提到的,这将允许完全模糊的重载。

本质上,您正在描述从static成员形成单例对象,共享一个常见的、合格的间接访问路径。为了使非const对象看起来是const,它必须通过某些方式访问,但没有this。它的decltype会改变吗?没有好的答案。如果您想要所有这些内容,请将它们明确地放在class对象中。


这是一个很好的观点。[[pure]]是一个扩展吗?我通常参考C++11的维基链接,但是简单的grep查找不到。 - iammilind
@iammilind [[pure]] 不是标准,我不认为任何平台都实现了它。但是 GCC 有 __attribute__((pure)),MSVC 也有类似的东西,如果我没记错的话。属性在某些情况下是有争议的,主要实现可能会抵制它们(请参见 Herb Sutter 最近的文章),因此像 [[pure]] 这样的东西可能永远不会具备可移植性。 - Potatoswatter

1

我的猜测是,在成员函数上使用staticconst来引用静态成员变量的常量性从未被考虑为一种选项。在我看来,你的建议是一种奇怪(但也许是明智的)混合这两个关键字的方式。


1

好问题。

我认为,概念上const适用于明确定义的对象或数据结构,而不适用于全局/静态等。

同样的道理,我可能会问为什么全局(或者特定于命名空间的)函数不能是const,也就是说它可以承诺不修改任何全局(或特定于命名空间的)变量。

在我看来,这没有太多意义。但是,对于属于特定类的静态成员的const性 - 在某些情况下,这可能是有用的。


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