22

重複の可能性:
クラス インスタンスでの C++ 静的メンバー メソッドの呼び出し

今日、C++ では違法と考えられていた長い間 (つまり、20 年間) 持っていたものが、実際には合法であることを発見しました。つまり、静的メンバー関数を、個々のオブジェクトに属しているかのように呼び出します。例えば:

struct Foo
{
    static void bar() { cout << "Whatever."; }
};

void caller()
{
    Foo foo;
    foo.bar();    // Legal -- what?
}

私は通常、静的メンバー関数が「スコープ解決構文」で厳密に呼び出されるのを目にします。したがって、次のようになります。

Foo::bar();

静的メンバー関数はクラスの特定のインスタンスに関連付けられていないため、これは理にかなっています。したがって、特定のインスタンスが関数呼び出しに構文的に「関連付けられている」とは思われません。

しかし、今日、GCC 4.2、GCC 4.7.1、および Clang 3.1 (コンパイラのランダム サンプリングとして) が前者の構文と次の構文を受け入れることを発見しました。

Foo* foo = new Foo;
foo->bar();

私の特定のケースでは、この表現の合法性が実行時エラーを引き起こし、この構文の特殊性は学術的な関心以上のものであると確信しました。それは実際的な結果をもたらします。

C++ では、静的メンバー関数を個々のオブジェクトの直接のメンバーであるかのように呼び出すことができるのはなぜですか。つまり、. または -> オブジェクトインスタンスにアタッチされた構文?

4

5 に答える 5

20

The Design and Evolution of C++の 288 ページで、Bjarne Stroustrup は、静的メンバー関数が登場する前の時代、プログラマーはオブジェクトを必要としないメンバー関数を呼び出すようなハックを使用していたと述べてい((X*)0)->f()ます。私の推測では、静的メンバー関数が言語に追加されたとき、アクセススルー->が許可されたため、そのようなコードを使用するプログラマーは、その使用ごとに探し出して変更fすることなく変更できるようになりました。static

于 2012-08-15T21:14:36.740 に答える
10

おそらく、何かのクラスタイプを知らないかもしれないが、コンパイラは知っている場所でそれを呼び出すことができるように。

クラス名を返す静的メンバーがそれぞれにあるクラスがたくさんあるとします。

class Foo
{
    static const char* ClassName() { return "Foo"; }
};

class Bar
{
    static const char* ClassName() { return "Bar"; }
};

次に、コード全体で次のようなことができます。

Foo foo;

printf( "This is a %s\n", foo.ClassName() );    

私のオブジェクトのクラスを常に知っていることを心配する必要はありません。これは、たとえばテンプレートを作成するときに非常に便利です。

于 2012-08-15T21:03:26.490 に答える
7

標準ではそれがどのように機能するかを示しているので、このようになります。n3290§9.4は次のように述べています。

クラスXの静的メンバーは、qualified-id式X::s;を使用して参照できます。静的メンバーを参照するために、クラスメンバーアクセス構文(5.2.5)を使用する必要はありません。静的メンバーは、クラスメンバーアクセス構文を使用して参照できます。その場合、オブジェクト式が評価されます。[ 例:

struct process { 
  static void reschedule(); 
}; 

process& g();

void f() { 
  process::reschedule(); // OK: no object necessary
  g().reschedule(); // g() is called 
} 

終了例]

于 2012-08-15T21:01:50.630 に答える
7

The Evolution of C++ (pdf) のセクション 8. Static Member Functionsから:

...次のような移植性のないコードも観察されました。

    ((x*)0)->f();

静的メンバー関数をシミュレートするために使用されました。

したがって、私の推測では、(他のほとんどすべての奇妙な構文上の理論的根拠のパターンに基づいて) 確立されているが壊れているイディオムとの下位互換性を提供する型があったときに、静的メンバー関数を呼び出すことができました。

于 2012-08-15T21:17:03.913 に答える
1

「標準がそう言っているので」因果関係の学校に加入しない場合は、静的メソッドは、this引数を関数呼び出しに渡すことによる余分なオーバーヘッドについて人々が実際に心配していた時代から来るのに十分古いこともお勧めします。したがって、最適化として純粋関数を「静的」にすることは、おそらく1985年に大流行しました。

于 2012-08-15T21:05:01.547 に答える