1. ホーム
  2. c++

[解決済み】静的リンクのあるメンバー関数

2022-02-17 09:55:58

質問

以下がエラーになる理由を知りたい。

class Foobar {
 public:
  static void do_something();
};

static void Foobar::do_something() {} // Error!

int main() {
  Foobar::do_something();
}

g++では "error: cannot declare member function 'static void Foobar::do_something()' to have static linkage" 、clang++では "error: 'static' can only be specified inside class definition" とエラーが出ます。

これを解決する方法は、6行目のdo_somethingの定義にある"static"を削除することだと理解しています。しかし、なぜこれが問題なのか理解できません。C++の文法がそう定めている、といったありふれた理由なのか、それとももっと複雑なことが起こっているのでしょうか?

解決方法は?

キーワード static はC++でいくつかの異なる意味を持ち、あなたが上に書いたコードはそれらを2つの異なる方法で使用しています。

メンバ関数の文脈で static は、「このメンバ関数はレシーバオブジェクトを持たない」という意味です。基本的には、クラスのスコープ内にネストされた通常の関数です。

関数宣言の文脈で static は、「この関数はこのファイルにのみスコープされ、他の場所から呼び出すことはできない」という意味です。

と書いて関数を実装した場合

static void Foobar::do_something() {} // Error!

を解釈した場合、コンパイラは static これは C++ では許されないことです。なぜなら、複数の異なるファイルがそれぞれ独自のメンバ関数の実装を定義し、それらを static リンク時の衝突を避けるために、同じメンバ関数を異なる場所から呼び出すと、異なる動作になってしまうのです!

幸いなことに、ご指摘の通り、簡単な修正が可能です。 static というキーワードを定義から削除しました。

void Foobar::do_something() {} // Should be good to go!

これは全く問題ありません。なぜなら、コンパイラはすでに do_somethingstatic のメンバー関数です。