web-dev-qa-db-ja.com

括弧で囲まれたメンバー関数のアドレスに関するエラー

面白いものを見つけました。エラーメッセージはそれをすべて言います。非静的メンバー関数のアドレスを取得するときに括弧を許可しない理由は何ですか? gcc 4.3.4でコンパイルしました。

#include <iostream>

class myfoo{
    public:
     int foo(int number){
         return (number*10);
     }
};

int main (int argc, char * const argv[]) {

    int (myfoo::*fPtr)(int) = NULL;

    fPtr = &(myfoo::foo);  // main.cpp:14

    return 0;

}

エラー:main.cpp:14:エラー:ISO C++は、非修飾または括弧で囲まれた非静的メンバー関数のアドレスを取得して、メンバー関数へのポインターを形成することを禁止します。 「&myfoo :: foo」と言います

33
Mahesh

エラーメッセージから、括弧で囲まれた式のアドレスを取得することが許可されていないようです。それはあなたが書き直すことを示唆しています

fPtr = &(myfoo::foo);  // main.cpp:14

fPtr = &myfoo::foo;

これは、仕様の一部(§5.3.1/ 3)が原因です。

メンバーへのポインターは、明示的な&が使用され、そのオペランドが修飾されたIDである場合にのみ形成されます括弧で囲まれていない [...]

(私の強調)。なぜこれがルールであるのかはわかりません(そして、今まで実際にこれを知りませんでした)が、コンパイラが不満を言っているようです。

お役に立てれば!

27
templatetypedef

このコードを想像してください:

struct B { int data; };
struct C { int data; };

struct A : B, C {
  void f() {
    // error: converting "int B::*" to "int*" ?
    int *bData = &B::data;

    // OK: a normal pointer
    int *bData = &(B::data);
  }
};

かっこを使ったトリックがないと、Bのデータメンバーへのポインターを直接取ることができません(ベースクラスのキャストと、thisを使用したゲームが必要です-ニースではありません)。


ARMから:

メンバーへのポインターを取得するには、アドレス演算子を明示的に使用する必要があることに注意してください。暗黙的な変換はありません...あるとしたら、メンバー関数のコンテキストにあいまいさが生じます...たとえば、

void B::f() {
    int B::* p = &B::i; // OK
    p = B::i; // error: B::i is an int
    p = &i; // error: '&i'means '&this->i' which is an 'int*'

    int *q = &i; // OK
    q = B::i; // error: 'B::i is an int
    q = &B::i; // error: '&B::i' is an 'int B::*'
}

ISは、この標準以前の概念をそのまま保持し、括弧がそれを作成することでメンバーへのポインターを取得しないことを明示的に述べました。