【问题标题】:Can't use "static" keyword on a static method in a c++ class implementation file (.cpp)不能在 C++ 类实现文件 (.cpp) 中的静态方法上使用“static”关键字
【发布时间】:2012-02-08 05:07:25
【问题描述】:

考虑:

//在Vector2.h中

class Vector2
{
    public:
        // returns the degrees in radians
        static double calcDir(double x, double y);
}

//在Vector2.cpp中

double Vector2::calcDir(double x, double y)
{
    double rad = ...;
    return rad;
}

为什么 Vector2.cpp 的签名中不需要关键字 static?当我尝试这个时,它会产生一个错误:

static double Vector2::calcDir(double x, double y)

这对我来说似乎不一致。方法签名的所有其他部分都需要在 .cpp 文件中重复(返回类型、方法名称(duh)、args 的名称和类型、常量)。我不喜欢一眼就知道方法是否是静态的(在查看实现时)。

这不仅不是必需的,而且是禁止的,有什么原因吗?

【问题讨论】:

  • 我认为这属于“因为标准是这样说的”。顺便说一句,virtual 也是如此。
  • virtual 也不需要重复。只有参与重载决议(和返回类型)的事情必须重复。
  • @Nathan Ernst:我从来没有意识到标准是自己写的。
  • 我不喜欢一眼就知道方法是否是静态的 - 我通过使用不同的情况来避免这种情况:Static()instance()跨度>
  • 我使用 cmets。 /*static*/ class::double blabla()。对于具有默认值的参数也是如此。 class:fun x(y = 0) 也不允许在定义中,所以我写class::fun x(y /*= 0*/)

标签: c++ static static-methods


【解决方案1】:

令人讨厌的是,关键字最终调用了两个非常不同的功能(全局到所有类实例与本地到文件),但以下小标题可能有用。宏只是扩展为一个空字符串,这意味着您可以在实现文件中的方法声明之前添加它,并在一年后回到您的代码中,您将避免通过 2000 行的“boost-esque”标题来找出为什么编译器不允许你使用它。

静态方法.h:

/*
** macro sugar for maintaining readability
** of static methods in implementation files
*/
#ifndef STATICMETHOD
#define STATICMETHOD

然后您可以在 .cpp 文件中使用:

#include "staticmethod.h"
STATICMETHOD double Vector2::calcDir(double x, double y)
{
    double rad = ...;
    return rad;
}

【讨论】:

    【解决方案2】:

    这是因为static 在类定义中使用时具有特殊含义。在类定义中,它将函数标识为静态成员函数,这意味着它不对类实例进行操作,但可以独立调用。

    static 类外部提供函数内部链接,但这在(甚至是静态)成员函数上是非法的,因为类成员必须与它们所属的类具有相同的链接(几乎总是外部的,当然在您可以在类定义之外定义成员函数的情况下为外部)。

    从语言的角度来看,类定义中的成员声明遵循一组语言规则,其中static 具有其特殊的类含义。在类定义之外,所有函数定义(成员和非成员)都遵循相同的规则集,其中 static 具有其他含义,这对于具有外部链接的类的成员无效。

    【讨论】:

    • “使用内部链接”有时是否通俗地称为“文件静态”?我认为这可能与此有关。
    • @SamuelMeacham:是的,有时使用“文件静态”而不是“内部链接”。
    【解决方案3】:

    这可能是为了减少混淆。在文件范围内,'关键字 static (令人困惑地)用来表示“使用内部链接”(TC++PL p.200)。这可能意味着该函数虽然是类的成员,但仅在当前翻译单元内可见。允许使用静态说明符会更加混乱。

    请注意,不再推荐使用 static 来表示内部链接,并且应该首选匿名命名空间来实现这一点。

    【讨论】:

    • 在匿名命名空间中声明的实体不会获得内部链接,除非它们也被声明为静态,它们只是获得翻译单元特定的名称。
    • 对于内部链接,匿名命名空间是否比静态命名空间更受欢迎?查尔斯的评论也很有趣,如果你真的想要内部链接,静态仍然是必需的。 @CharlesBailey,使用翻译单元特定名称,您是否仍然获得与内部链接相同的最终结果?意思是,人们是否意识到不使用静态他们没有获得内部联系,但不在乎?自从我每天使用 c++(我使用 c# 工作)以来已经有一段时间了,但我对这门语言有着深深的热爱,并希望重新回到游戏中 =)
    • 据我所知,实际上没有区别,因此是“”。该标准有一个注释:“尽管未命名命名空间中的实体可能具有外部链接,但它们实际上是由其翻译单元唯一的名称限定的,因此永远无法从任何其他翻译单元中看到。”
    • @CharlesBailey 感谢您的澄清 =)
    猜你喜欢
    • 2021-06-21
    • 1970-01-01
    • 2020-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-08
    • 2011-07-19
    相关资源
    最近更新 更多