2011-06-30 30 views
1

私は関数FooとクラスCDelegateを持っています。 CSpi1::m_Delegate();関数ポインタへのconst参照

:私は私の静的オブジェクトの()演算子を呼び出すことによって Fooを呼び出したい

CInterruptDelegate CSpi1::m_Delegate(FreeFunction, 0); 

typedef void (*typeFctPtr)(void*); 


void Foo(void* dummy) 
{ 
    cout << "Foo\n"; 
} 


class CDelegate 
{ 
    public: 

    CDelegate (const typeFctPtr& f_ref_Wrapper, void* f_pvSubscriber) 
    : m_ref_Wrapper(f_ref_Wrapper), m_pvSubscriber(f_pvSubscriber) 
    { 
    } 

    inline void operator()() const 
    { 
    (*m_ref_Wrapper)(0); 
    } 

    inline void operator=(const CInterruptDelegate& D) 
    { 
    } 

private: 
    void* m_pvSubscriber; 
    const typeFctPtr& m_ref_Wrapper; 
}; 

第二のクラスは、私はこのようなコンストラクタを使用して初期化する静的メンバstatic CDelegate m_Delegate;を持っています

例外が発生しました(*m_ref_Wrapper)(0); 構文に問題がありますか?私がしようとしていることがまったく可能であるかどうかは、私は確信していません。私は、CDelegateのコンストラクタが関数ポインタのconst参照を取っておらず、関数ポインタ自体を取るという実用的な解決法を持っています。私は問題なしで()演算子で関数を呼び出すことができます。関数のポインタ呼び出しを最適化できず、コンパイル時にすべてを知る必要があるので、const参照を使用して呼び出しを行うことを願っています。

+0

あなたは単に 'm_ref_Wrapper(0)を呼び出す試してみましたか;'? – iammilind

+0

オプティマイザが、参照またはポインタのどちらかを使って間接呼び出しを削除できる場合、私は驚いています。しかし、間接的な呼び出しは本当にそれほど高価ではありません。 –

+0

@Cat Plus Plusでは、このメカニズムを組み込みシステムでの割り込み処理に使用しています。 boost :: functionは私が必要とするすべてを行いますが、遅いです。また、関数ポインタとして引数を取ってソフトウェアが動作しています。私は今const参照を使用して最適化したいです...少なくとも試みる:) – Mirco

答えて

1

あなたは関数へのポインタへの参照を保持しています(ポインタは、使用するまでに破棄された一時的なものなので、状況はひどく間違っています)。

は、関数型であるためにあなたのtypedefを変更してみてください:

typedef void typeFct(void*); 
... 
const typeFct & m_ref_Wrapper; 

は、その後、あなたの既存のコードを使用すると、関数への参照になってしまいます、あなたは大丈夫です。または、関数へのポインタを格納することができます - const typeFct *

どちらの場合でも、コールはm_ref_Wrapper(0)になります。

一般的に私は、構文があいまいであるためにのみ、ポインターまたは参照先ではなく関数型をtypedefすることをお勧めします。

+0

ありがとう、私はこれをコンパイルすることができ、私は実行タイマーのエラーを取得しません。しかし警告が表示されます。警告C4180:関数型に適用される修飾子は意味を持ちません。 (const typeFct&f_ref_Wrapper、void * f_pvSubscriber) 'と' const typeFct&m_ref_Wrapper; – Mirco

+0

@Mircoはい、私の間違いです。どこでもtypeFctにconstが適用されるべきではありません。 constはデータにとっては意味があり、関数には意味がありません。 –

1

私はこの問題は、メンバーの宣言であると信じています:

const typeFctPtr& m_ref_Wrapper; 

代わりに、&を削除しよう:

const typeFctPtr m_ref_Wrapper; 

参照が常に別の既存のオブジェクトを参照する必要があります。この場合、作成された一時オブジェクトを参照して、コンストラクターの呼び出し時に参照を保持します。

私たちはそれに取り組んでいますが、コンストラクタからの参照も削除することをお勧めします。この理由は、スカラーで作業するときに利益がないからです。

コードをより読みやすくするもう1つのことは、関数へのポインタではなく、関数の型をtypedefする場合です。そうすれば、ポインタを渡すことは明らかです。

次の変更をまとめたカットダウン版です私は上記の提案:

typedef void (typeFct)(void*); 

class CDelegate 
{ 
    public: 

    CDelegate (typeFct * f_Wrapper, void* f_pvSubscriber) 
    : m_ref_Wrapper(f_Wrapper), m_pvSubscriber(f_pvSubscriber) 
    { 
    } 

    inline void operator()() const 
    { 
    (*m_ref_Wrapper)(0); 
    } 

private: 
    void* m_pvSubscriber; 
    typeFct * m_ref_Wrapper; 
}; 
+0

+1公正な公正だと思われる –

+0

ありがとう! Btw、私はあなたのポストから何か新しいことを学んだ、私はあなたが関数への参照を行うことができるか分からなかった。 – Lindydancer

+0

@Lindydancer、私は、これは私の実用的な解決策は、typedefの違いを1つの参照を使用する代わりに、関数ポインタを使用していると思う。私はこれを覚えて、将来関数の型をtypedefします:)残念ながら私は+1できません(まだ<15)。 – Mirco

関連する問題