How to easily override multiple overloaded methods?

Let's say I have an interface and a class implementing it, like this:

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:
    ...
}

And then I decide to add a simple decorator class, like this:

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);
    }
}

Now, all this is pretty simple and straightforward. The problem is that there is a lot of code duplication in the SwitchablePrinter implementation. I was wondering, that if there was a way to write a generic method 'print' for all overloaded methods in the base class, like this:

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

I think there may be a solution using templates, but I am not very experienced with using them and need advice.


Although there is no mechanism to override multiple member functions at once, you can simplify your task and reduce code duplication by providing a private variadic member function template that forwards the call to the proper overload of the wrapped _printer , like this:

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.

This is only a slight improvement on the original, because the forwarding logic of print_impl is so simple. When the logic becomes more complex, payoff from sharing the code increases.


The obvious thing to try is to replace the implementations in SwitchablePrinter with

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

(ignoring that there's a problem with the integer printing method.)

But this doesn't work, because member function templates cannot be virtual: Can a C++ class member function template be virtual?. (See the most upvoted answer, rather than the accepted one.) So your current implementation of SwitchablePrinter is the best, as far as I can see.

链接地址: http://www.djcxy.com/p/88364.html

上一篇: gulp,在`pipe()`函数中使用当前文件名

下一篇: 如何轻松覆盖多个重载的方法?