Невозможно использовать статическое ключевое слово для статического метода в файле реализации класса С++ (.cpp)

Рассмотрим:

//В 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), имена и типы аргументов, константа). Мне не нравится не знать с первого взгляда, является ли метод статическим или нет (при просмотре реализации).

Есть ли причина, по которой это не только не требуется, но и запрещено?

Ответ 1

Это потому, что static имеет особое значение при использовании в определении класса. В определении класса он идентифицирует функцию как статическую функцию-член, что означает, что она не работает с экземпляром класса, но может быть вызвана независимо.

Вне класса static дается внутренняя связь функции, но это незаконно (даже статические) функции-члены, поскольку члены класса должны иметь ту же связь, что и класс, членом которого он является (почти всегда внешний и, конечно, внешний в случаях, когда вы можете определить функции-члены за пределами определения класса).

С точки зрения языка объявление членов внутри определения класса следует одному набору языковых правил, где static имеет свое особое значение класса. Вне определения класса все определения функций - члены и нечлены - следуют одному и тому же набору правил, где static имеет другое значение, которое недействительно для членов классов с внешней связью.

Ответ 2

Это, вероятно, для уменьшения путаницы. В области файлов "ключевое слово static (смутно) используется для обозначения" использовать внутреннюю связь "(TС++ PL p.200). Это может означать, что функция, хотя и является членом класса, была видна только внутри текущей единицы перевода. Разрешение статического спецификатора было бы более запутанным.

Обратите внимание, что использование static для обозначения внутренней привязки больше не рекомендуется, и чтобы анонимные пространства имен были предпочтительнее этого.

Ответ 3

Досадно, что ключевое слово запущено, вызывая две очень разные функции (от глобальных до всех-класса-экземпляров и от локального к файлу), но может понадобиться следующий небольшой заголовок. Макрос просто расширяется до пустой строки, что означает, что вы можете использовать его перед декларациями методов в файле реализации и вернуться к вашему коду через год, вы избежите пролистывания через 2000-строчный заголовок "boost-esque" узнайте, почему компилятор не позволит вам использовать это.

staticmethod.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;
}