如何轻松地覆盖多个重载方法

How to easily override multiple overloaded methods?

本文关键字:重载 方法 覆盖 何轻松      更新时间:2023-10-16

假设我有一个接口和一个实现它的类,像这样:

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

我认为使用模板可能有一个解决方案,但我对使用它们不是很有经验,需要建议。

虽然没有机制可以一次覆盖多个成员函数,但是您可以通过提供一个私有可变成员函数模板来简化您的任务并减少代码重复,该模板将调用转发给包装的_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);
    }

演示。

由于print_impl的转发逻辑非常简单,所以这只是在原来的基础上的一个小小的改进。当逻辑变得更复杂时,共享代码的收益就会增加。

显然要尝试用

替换SwitchablePrinter中的实现。
template<typename T>
void print(T t) override
{
    if (_enabled)
        _printer.print(t);
}

(忽略整数打印方法存在问题)

但是这不起作用,因为成员函数模板不能是虚的:c++类成员函数模板可以是虚的吗?(请参阅点赞最多的答案,而不是公认的答案。)所以你目前的SwitchablePrinter实现是最好的,就我所见。