2

X プラットフォーム フレームワークとして JUCE を使用しています。テンプレート リスナー クラスを使用して、ボタン/コンボボックスなどのコールバックを特定のハンドラー関数にマップしています。さまざまなウィジェットには独自のコールバック関数名があるため、次の構造を使用します。

template<typename Type, typename Widget>
class ListenerBase : public Widget::Listener
{
public:
  typedef void (Type::*TCallbackType)(void);
protected:
  void notifyCallback(Widget* notifier)
  {
  ...
  }
  void addHandler(Widget* notifier, TCallbackType callback)
  {
    notifier->addListener(this);
  ...
  }
};

template<typename Type>
class ButtonListenerHandler : public ListenerBase<Type, Button>
{
protected:
  void buttonClicked(Button* btn)
  {
     notifyCallback(btn);
  }
};

template<typename Type>
class LabelListenerHandler : public ListenerBase<Type, Label>
{
protected:
  void labelTextChanged(Label* lbl)
  {
     notifyCallback(lbl);
  }
};

そして、クラスでハンドラーの特殊化を 1 つだけ使用する限り、問題なく動作します。複数を使用するとすぐに、コンパイラが addHandler(Button*, ...) と addHandler(Label*, ...) を区別できないかのように、VC++ 2008 は addHandler 呼び出し間のあいまいさを訴えます !! これらの関数はテンプレート化されているため、プロトタイプが異なるため、コンパイラが苦労している理由がわかりません。アイデア?

リクエストによる編集:

異なるリスナーを持つクラスは次のようになります。

class MyClass : public ButtonListenerHandler<MyClass>
              , public LabelListenerHandler<MyClass>
{
...
   void buttonHandlerFunction();
   void labelHandlerFunction();

   Button* m_btn;
   Label* m_label;
};

エラーが発生する場所:

MyClass::MyClass()
{
...
   addHandler(m_btn, &MyClass::buttonHandlerFunction);  <<< error
   addHandler(m_label, &MyClass::labelHandlerFunction);  <<< error
}

エラーは次のとおりです。

1>MyClass.cpp(287) : error C2385: ambiguous access of 'addHandler'
1>        could be the 'addHandler' in base 'ListenerBase<MyClass,juce::Button>'
1>        or could be the 'addHandler' in base 'ListenerBase<MyClass,juce::Label>'
4

1 に答える 1

0

編集
さて、すべてを再考した後、問題は関数にありListenerBase<MyClass, Button>ListenerBase<MyClass, Label>それぞれが関数を定義します。継承のため、署名が異なっていても(1つはパラメーターを持ち、もう1つは1つ) addHandler、オーバーロードとしてカウントされないようです。これに対して私が見つけた1つの可能な修正は、への呼び出しを完全に修飾することです。少し冗長で、実際には望まれていないかもしれませんが、機能します(便宜上、基本クラスを使用しました)。Button*Label*addHandlertypedef

template<class Type>
class ButtonListenerHandler : public ListenerBase<Type, Button>{
public:
    typedef ListenerBase<Type, Button> ButtonListenerBase;
};

template<class Type>
class LabelListenerHandler : public ListenerBase<Type, Label>{
public:
    typedef ListenerBase<Type, Label> LabelListenerBase;
};

class MyClass : public ButtonListenerHandler<MyClass>,
                public LabelListenerHandler<MyClass>{
public:
    void buttonHandlerFunction();
    void labelHandlerFunction();

    MyClass(){
        ButtonListenerHandler<MyClass>::addHandler(m_btn, &MyClass::buttonHandlerFunction);
        LabelListenerHandler<MyClass>::addHandler(m_label, &MyClass::labelHandlerFunction);
    }

private:
    Button* m_btn;
    Label* m_label;
};

'別の編集ここでの私の質問
に対する迅速な回答のおかげで、私はそれに別の編集を与えることができます。そこに記載されている方法は、問題にも当てはまります。:)using

class MyClass : public ButtonListenerHandler<MyClass>,
    public LabelListenerHandler<MyClass>{
public:
    using ButtonListenerHandler<MyClass>::addHandler;
    using LabelListener<MyClass>::addHandler;

    void buttonHandlerFunction(){
    }
    void labelHandlerFunction(){
    }

    MyClass(){
        addHandler(m_btn, &MyClass::buttonHandlerFunction);
        addHandler(m_label, &MyClass::labelHandlerFunction);
    }

private:
    Button* m_btn;
    Label* m_label;
};
于 2011-03-20T12:18:52.270 に答える