2011-12-23 70 views
2

假設我有用C++ 98構建的偵聽器,它們是抽象的,並且必須例如實現ActionPerformed。在C++ 0x中是有辦法做到這類似於Java:C++ 0x是否支持匿名內部類?

button.addActionListener(new ActionListener() { 
public void actionPerfored(ActionEvent e) 
{ 
// do something. 
} 
}); 

感謝

回答

6

不完全是,但你可以做一些與蘭姆達斯關係密切。

即:

class ActionListener 
{ 
public: 
    typedef std::function<void(ActionEvent&)> ActionCallback; 

public: 
    ActionListener(ActionCallback cb) 
     :_callback(cb) 
    {} 

    void fire(ActionEvent& e) 
    { 
     _callback(e); 
    } 

private: 
    ActionCallback _callback; 
}; 


.. 
button.addActionListener(new ActionListener(
    [](ActionEvent& e) 
    { 
     ... 
    } 
)); 
+4

一個合適的C++接口當然會有任何這樣的「addActionListener」帶一個* proper * functor,一個重載'operator()',而不是覆蓋一個虛函數並依賴於繼承。 – 2011-12-23 18:15:04

5

不,你不能這樣做。

如果你放棄了「類似於Java」,但是隻使用一個函子,你會發現C++ 11 lambda非常有用。

+0

問題是我有很多代碼使用Java的方式做到這一點,蘭姆達斯不能幫助這裏。 – jmasterx 2011-12-23 05:16:24

+0

你不能用Java的方式來做,所以你必須找到另一種方式,而Lambdas肯定可以幫你。 – Gerald 2011-12-23 06:51:27

+7

您有很多* C++代碼*使用Java方法?試圖假裝C++是Java是不理想的,並且肯定會讓你的生活變得悲慘。 – 2011-12-23 07:27:03

5

這是C++,而不是Java,因此像Java一樣編寫C++將無法正常工作。

無論如何,你可以創建一個適配器功能。假設

typedef int ActionEvent; // <-- just for testing 

class ActionListener 
{ 
public: 
    virtual void actionPerformed(const ActionEvent& event) = 0; 
}; 

然後,我們可以寫的ActionListener的模板子類,包裝了一個函數對象:

#include <memory> 

template <typename F> 
class ActionListenerFunctor final : public ActionListener 
{ 
public: 
    template <typename T> 
    ActionListenerFunctor(T&& function) 
     : _function(std::forward<T>(function)) {} 

    virtual void actionPerformed(const ActionEvent& event) 
    { 
     _function(event); 
    } 
private: 
    F _function; 
}; 

template <typename F> 
std::unique_ptr<ActionListenerFunctor<F>> make_action_listener(F&& function) 
{ 
    auto ptr = new ActionListenerFunctor<F>(std::forward<F>(function)); 
    return std::unique_ptr<ActionListenerFunctor<F>>(ptr); 
} 

,然後用make_action_listener包拉姆達e.g(http://ideone.com/SQaLz)。

#include <iostream> 

void addActionListener(std::shared_ptr<ActionListener> listener) 
{ 
    ActionEvent e = 12; 
    listener->actionPerformed(e); 
} 

int main() 
{ 
    addActionListener(make_action_listener([](const ActionEvent& event) 
    { 
     std::cout << event << std::endl; 
    })); 
} 

注意,這絕不是地道的C++,在addActionListener(),你應該簡單地採取const std::function<void(const ActionEvent&)>&,甚至獲得最高效率的模板參數,並直接提供拉姆達。

1

我認爲,我們可以在C做++使用lambda表達式

button.addActionListener([]()->ActionListener*{ struct A: ActionListener { 
void actionPerfored(ActionEvent e) 
{ 
// do something. 
} 
}; return new A;}()); 

它應該很容易在宏來包裝這件事。

+1

太糟糕了,我們不能'''{return new struct:ActionListener {...}; }'。這實際上看起來很像Java版本... – Xeo 2012-01-23 01:08:24