为啥静态成员函数只能在类定义中声明为静态,而不能在其自己的定义中声明?

Posted

技术标签:

【中文标题】为啥静态成员函数只能在类定义中声明为静态,而不能在其自己的定义中声明?【英文标题】:Why can a static member function only be declared static inside the class definition and not also in its own definition?为什么静态成员函数只能在类定义中声明为静态,而不能在其自己的定义中声明? 【发布时间】:2014-11-16 14:34:35 【问题描述】:

在实现一个用于在屏幕上创建/更新框的类时,我想添加一个静态成员函数,以确保没有当前可见的框重叠(将其信息从静态指针数组获取到所有当前可见的框)

我的初始代码具有以下结构:

class Box

public:
    // ...
    static void arrangeOverlappingBoxes();
;

static void Box::arrangeOverlappingBoxes()

    // ...

我很惊讶这会产生错误 C2724: 'static' should not be used on member functions defined at file scope.

经过一些试验、google 和错误,我发现我的函数定义应该丢失关键字 static,即应该是

void Box::arrangeOverlappingBoxes()

    // ...

但我不知道这背后的基本原理是什么。在类定义和自己的定义中声明不同的函数头似乎是不对称和混乱的。这有什么原因吗?

【问题讨论】:

【参考方案1】:

您的类定义(在头文件中)将为函数提供所需的任何属性:

静态 内联 虚拟

考虑到每个进一步的对象都将使用 .h 查看您的类定义,那么在此处定义这些属性是有意义的。

此外,类中的每个函数都将在派生类中保留其属性(例如,您只需在基类中声明析构函数为虚拟,随后的每个继承都将析构函数视为虚拟)。

在您的实现主体中重新声明这些属性是没有意义的。

必须在 .h 和 .cpp 文件中声明函数属性实际上会导致很多问题。 想象一下这种情况:您在 .h 文件中将函数声明为虚拟函数,在 .cpp 文件中声明为静态函数。编译器会做什么?虚拟的还是静态的? (或者更可能是编译错误,但编译器错误只会敦促您在 .cpp 文件中匹配标头中的声明。您不能根据“静态”或“虚拟”重载函数)。

【讨论】:

感谢您的回答,但我仍然不明白这一点。编译器可以被编程为在属性相同的情况下进行编译,就像参数应该相等一样(事实上,Java语法要求它是这样的)。那你为什么说它没有意义呢?以我的拙见,这很有意义:如果您只查看您的 cpp 文件(假设您的类定义在标题中),您会立即看到该函数是静态的,并且例如没有 this 指针无需查看头文件。 这样想:如果允许在 .cpp 和 .h 中指定函数的类型,会出现什么问题?您将看到编译器实际上会强制您在 .cpp 中使用与头文件中相同的属性来实现函数,否则您将收到未解决的外部符号链接错误(请记住,所有外部类都与标题中的函数)。因此,在 cpp 文件中也必须声明此属性会产生反作用。 C++ 本身就足够复杂,不需要额外的挑战;)。 关于您编辑的评论:您可以使用命名约定或 cmets 来为“静态”或此类属性添加下划线。当涉及到方法类型时,我个人会查看头文件(你有去声明并去定义)......也许这是一个风格问题 谢谢,命名约定确实是我处理它的方式,但是我还没有完全相信在声明和定义中要求相等的签名(名称、参数和属性)会适得其反。它在最近的语言中以不同的方式实现这一事实使我将其视为 C++ 怪癖。 最近有哪些语言允许您在类内将函数声明为静态函数,在类外将函数声明为非静态函数(当然要保持相同的函数)?

以上是关于为啥静态成员函数只能在类定义中声明为静态,而不能在其自己的定义中声明?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能只用前向声明 C++ 声明一个类的静态成员?

C++中类里面定义 静态成员变量的问题

C++中static函数类外定义的时候为啥不写static?

将线程函数声明为静态函数的问题

C++ 静态成员函数

C++ 静态成员函数