2015-10-19 51 views
7

比方說,我有一個接口,並實現它的一類,像這樣:如何輕鬆覆蓋多個重載方法?

class IPrinter 
{ 
public: 
    virtual void print(int i, int base = 10) = 0; 
    virtual void print(char c) = 0; 
    virtual void print(char *s) = 0; 
    virtual void print(float f) = 0; 
    virtual void print(double d) = 0; 
    virtual ~IPrinter() = default; 
private: 
    ... 
} 

class Printer : public IPrinter 
{ 
public: 
    void print(int i, int base = 10) override {...} 
    void print(char c) override {...} 
    void print(char *s) override {...} 
    void print(float f) override {...} 
    void print(double d) override {...} 
private: 
    ... 
} 

然後我決定增加一個簡單的裝飾類,像這樣:

class SwitchablePrinter : public IPrinter 
{ 
private: 
    IPrinter& _printer; 
    bool _enabled; 
    ... 
public: 
    SwitchablePrinter(IPrinter& p) : 
     _printer(p), 
     _enabled(true) 
    { 
    } 

    void print_enable(bool on) { _enabled = on; } 

    void print(int i, int base = 10) override 
    { 
     if (_enabled) 
      _printer.print(i, base); 
    } 
    void print(char c) override 
    { 
     if (_enabled) 
      _printer.print(c); 
    } 
    void print(char *s) override 
    { 
     if (_enabled) 
      _printer.print(s); 
    } 
    void print(float f) override 
    { 
     if (_enabled) 
      _printer.print(f); 
    } 
    void print(double d) override 
    { 
     if (_enabled) 
      _printer.print(d); 
    } 
} 

現在,這一切都是非常簡單和直接。 問題是SwitchablePrinter實現中有很多代碼重複。我在想,如果有是寫在基類中的所有重載方法的通用方法「打印」,像這樣的方式:

(pseudo-code) 
void print({any args}) 
{ 
    if (_enabled) 
     _printer.print({any args}); 
} 

我覺得有可能是使用模板的解決方案,但我對使用它們並不很熟練,需要建議。

+1

不,沒有。你的代碼也不會如你所願,你需要在打印機中添加虛擬來覆蓋功能。 你可以使用boost :: variant和一個函數來代替所有的重載。 –

+6

@KlemensMorgenstern,「你需要在打印機中添加虛擬」不,不是。 – SingerOfTheFall

+1

嗯,由於重寫,你可以跳過虛擬?很好,我不知道。 –

回答

4

儘管沒有機制可以一次覆蓋多個成員函數,但可以通過提供私有可變成員函數模板來簡化任務並減少代碼重複,該模板將調用轉發到包裝的_printer的正確過載,如下所示:

private: 
    template <class ... T> 
    void print_impl(T ... vals) { 
     if (_enabled) 
      _printer.print(vals...); 
     else 
      cout << "disabled" << endl; 
    } 
public: 
    void print(int i, int r) override { 
     print_impl(i, r); 
    } 
    void print(float f) override { 
     print_impl(f); 
    } 
    void print(double d) override { 
     print_impl(d); 
    } 
    void print(char* s) override { 
     print_impl(s); 
    } 
    void print(char c) override { 
     print_impl(c); 
    } 

Demo.

這是僅允許在原始略有改善,因爲print_impl轉發邏輯是如此簡單。當邏輯變得更復雜時,共享代碼的收益會增加。

+3

爲了處理'int'的情況,如何使'print_impl'成爲可變參數?如果我們不擔心完美的轉發,它會增加最少的語法開銷。 –

+0

@VaughnCato你是對的,這使得更好的實施。非常感謝你! – dasblinkenlight

0

最明顯的地方就是與

template<typename T> 
void print(T t) override 
{ 
    if (_enabled) 
     _printer.print(t); 
} 

替換SwitchablePrinter的實現(忽略有與整數印刷方法的問題。)

但是,這並不工作,因爲成員功能模板不能是虛擬的:Can a C++ class member function template be virtual?。 (請參閱最高評價的答案,而不是接受的答案。)因此,就目前我看來,您當前的SwitchablePrinter實施方案是最好的。