English 中文(简体)
我如何界定在C++中接受衍生成员职能点的一类方法?
原标题:How I do define a class method that accepts a derived class member function pointer as a parameter in C++?

I m 采用信号-Slot C++执行,见:。 在用户接口图书馆Im发展中安装活动听众。

用户浏览器也一样:

class DialEventListener : public EventListener {

    void handleEvent(Event event){
        …
        cout << "Event on" << event.source.name << end;
    }
}
int main(){
    Interactor dial1;
    dial1.addListener(ROTATE_EVENT, DialEventListener());
    … 
}

为界定活动听众,用户将分级<密码>,以创建习惯活动手稿。 但在实施<代码>Interactor:addListener()时,我使用信号码。

下面是一部显示我如何试图利用信号执行活动听众的密码。 我使用<代码>的地图。 活动类型至<代码>,以说明触发多种类型活动的相互作用。

typedef map< EventType, Signal1<Event> > EventTypeListenerMap;
class Interactor {

private:
   EventTypeListenerMap listener_map;

public:
   void TriggerEvent(Event e){
       Signal1<Event> signal = listener_map[e.type];
       signal(e);
   }

   void addListener(EventType e_type, EventListener listener){
      …
          //Find the signal for a particular kind of event.
      Signal1<TUIKitEvent> signal = listener_map[e_type];
          //Plug a delegate into that signal s slot
      signal.Connect( &listener, &EventListener::handleEvent); 
   }
   void addListener(EventType e_type, EventListener listener, void (EventListener::*handler)(Event)){
      …
      Signal1<TUIKitEvent> signal = listener_map[e_type];
      signal.Connect( &listener, handler); 
   }

}    

class EventListener  {
    virtual void handleEvent(Event event){
    }
}

使用信号定位装置的Im应当隐藏在用户身上,因此我刚刚写了这一版本的<代码>。 Interactor:addListener (EventType, FinalListener, void (EventListener:*) as a sanityeck to ensure I was through the right member function pointer to be subject to this sign. 但是,成员职能点是具体类别,因此,如何界定一个功能,其签名是接受从事件类型学到的方法,而这种方法可能还不存在?

最佳回答

有两个回响办法,要么是你提供一种称为虚拟功能的接口,要么是你履行型-erasure,使之完全通用。 在第二版中,你要么为 类型-erasure使用预先包装的解决办法。 或您将需要使用一些模板来实施。

您在首批中展示的预期用户代码遵循了第一个方法,足以满足基本需求。 但指出,你可能想在你通过的价值的多个地方使用点或参考点:

// user code
Interactor dial;
DialEventListener dial_listener;
dial.addListener( ROTATE_EVENT, dial_listener );

// implementation
void Interactor::addListener( EventType event, EventListener & listener ) {
   Signal1<TUIKitEvent> & sgn = listener_map[event];
   sgn.Connect( &listener, &EventListener::handleEvent );
};

注:<代码>listener的论点以参考而不是价值通过。 如果你以价值通过,你将获得slicing。 (只有EventListener的次级目标将加以复制,不会成为DialEventListener。 载于<代码>addListener内的物体。 通过提及基类,在物体保持其特性时,你可以将其用作基数。

而这反过来又要求你通过的目标不是临时性的(不能使用<>Dial EventListener(<>>>/code>作为第二条理由进入addListener<>/code>,因为临时寿命将在全部表述的末尾结束,这意味着你将有一个 d的参照(在你目前执行过程中,你在信号执行中有一个ling点,在信号发出后,这很可能造成UB)。

此外,addListener 页: 1 地图上储存的信号,但又加以修改,在获取地图上信号时,你应使用参考而不是价值。

您的类别文件应当明确无误,因为通过该物体的寿命必须超出Interactor(或允许de Registration<>m>,以便客户能够在打退之前从Interactor中删除手稿(如果你在UB上不会结束,则)

另一种做法是: 类型-erasure,我从未使用过这一特殊信号图书馆,因此我在这里耳光。 您正在使用的信号图书馆(可能)在内部实施类型功能,但是,在校准能够完成时代之前,你需要能够转播准确的类型,或者在接口中使用不同类型的时段图书馆。

// Transferring the exact type to the signal lib:
class Interactor {
// ...
public:
   template <typename Listener>
   void addListener( EventType event, Listener & listener, void (Listener::*callback)(Event) ) {
      Signal1<TUIKitEvent> & sgn = listener_map[event];
      sgn.connect( &listener, callback );
   }
//...

Using a different type erasure library in the interface might or not be possible depending on the semantics of the connect method in your signals implementation. If it copies the first argument, then you can probably make do with std::function:

class Interactor {
//...
public:
   void addListener( EventType event, std::function< void (Event) > callback ) {
       Signal1<TUIKitEvent> & sgn = listener_map[event];
       sgn.connect( callback, &std::function<void(Event)>::operator() );
   }
//...
};

Assuming that the library will copy the first argument and maintain it s own copy internally (i.e. assuming that it behaves somehow like boost::signal library). On the user side, they will have to perform the type erasure:

struct AnotherListener {   // no need to explicitly derive from EventListner now!
   void method( Event e ) {}
};
int main() {
   Interactor dial;
   AnotherEventListener listener;
   dial.addListener( dial, std::bind( &AnotherListener::method, &listener ) );
}

<代码>bind的确切辛醇/编码可能不是,我从未在提升图书馆使用过新标准,而是将使用<代码>boost:bind( &AnotherListener:method, &listener, ;......

问题回答

暂无回答




相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?