5

そのフィールドとして関数へのポインターと、保持している構造体へのポインターが引数であるように保持できるクラスが必要です。そのオブジェクトのインターフェースは、引数を取らずに保存された引数を上記の関数に渡すメソッドcall()になります。さまざまな引数のタイプとカウントに対するこのようなクラスのファミリーには、仮想の呼び出しを持つ共通の抽象祖先があります。

今のところ、次のコードが機能しますが、g++に-pedanticオプションを追加するとエラーが発生します。

class Function {
    protected:
    void *data;
    void *function;
    public:
    virtual void call() = 0;
};

class SingleArgumentFunction : public Function {
    public:
    SingleArgumentFunction( void (*f)(int), int i ) {
        int *icpy = new int(i);
        function = (void*) f;
        data = (void*) icpy;
    }
    ~SingleArgumentFunction() { delete (int*)data; }
    inline void call() {
        ( *((void (*)(int))function) )( *(int*)data );
    }
};

私が得るエラーは、タイトルが言うようにです:

warning: ISO C++ forbids casting between pointer-to-function and pointer-to-object

それをどのように処理しますか?

4

2 に答える 2

10

ポインタから関数のポインタからオブジェクトへのポインタをキャストしないでください。同じサイズであることが保証されているわけではありません。void(*)()代わりに関数ポインタを使用することで、この問題を回避できます。

C99 [6.2.5 / 27]:

voidへのポインタは、文字型へのポインタと同じ表現および配置要件を持つ必要があります。同様に、互換性のあるタイプの修飾バージョンまたは非修飾バージョンへのポインターは、同じ表現および配置要件を持つ必要があります。構造体タイプへのすべてのポインタは、互いに同じ表現と配置の要件を持つ必要があります。共用体型へのすべてのポインターは、互いに同じ表現および配置要件を持つ必要があります。他のタイプへのポインタは、同じ表現または配置要件を持つ必要はありません。

C99 [6.3.2.3 / 8]:

あるタイプの関数へのポインターは、別のタイプの関数へのポインターに変換され、また元に戻される場合があります。結果は元のポインタと同じになります。

この他のSO回答から取られた参照。


ちなみに、あなたは再現しようとしているようですstd::function+std::bind

std::function< void() > f;
f = std::bind( &some_function_that_takes_an_int, 42 );

f(); // look ma! no arguments
于 2013-01-27T02:21:12.490 に答える
4

関数ポインタをとして必要とするAPIを使用せざるを得ない場合はvoid*、警告を生成するステートメントの前に、その警告__extension__を消音することができます。これはgcc固有であるため、その単語を保護するのが最善です。

#ifdef __GNUC__
__extension__
#endif
the_statement_that_includes_the_cast;

http://trac.osgeo.org/qgis/ticket/234から。

于 2013-09-30T11:26:50.300 に答える