带有抽象继承的后缀操作符++



我想在结构层次结构中实现前缀和后缀操作符++(抽象基类a和子类B)。当只在基类中实现前缀时,这工作得很好。然而,当在子类中实现后缀版本时(因为它不能在抽象类中实现),它不起作用。

struct A {
    virtual A& operator++(){std::cout << "A: prefix ++" << std::endl; return *this;}
    virtual void foo() = 0;
};
struct B : A {
    void foo() override {};
    //virtual B& operator++() override {std::cout << "B: prefix ++" << std::endl; return *this;}
    //B operator++(int i) {std::cout << "B: postfix ++" << std::endl; return *this;}
};
int main(int argc, const char * argv[]) {
    B b;
    ++b; // Compile error here if I implement postfix in B
    return 0;
}

问题是我想避免重复代码,因为所有派生类都将以相同的方式使用operator++,所以最好不要在各自的类中实现它们。使用抽象类的全部意义就是避免这种情况!

我的问题是:解决这个问题的最优雅的方法是什么?

编辑。错误消息:不能增加类型'B'的值

问题是派生类中的operator++隐藏了基类中的名称。尝试将以下内容添加到B:

using A::operator++;

您可能会发现很难使后增量函数具有多态行为。协变返回类型不能工作。

现场演示。

既然您要求一种更优雅的方法来做到这一点,我认为最优雅的方法是尽可能地对类的消费者隐藏多态接口的细节。

再多一个包含多态概念的类就可以了,并允许您轻松安全地实现后增量:

#include <memory>
#include <iostream>
// this is our non-polymorphic handle class. In this case each handle
// owns a discrete object. We could change this to shared-handle semantics by using shared_ptr if desired.
struct poly_thing
{
    // this is the polymorphic concept (interface)
    struct concept {
        virtual void increment() = 0;
        virtual std::unique_ptr<concept> clone() const = 0;
        virtual ~concept() = default;
    };
    poly_thing(std::unique_ptr<concept> p_concept)
    : _impl(std::move(p_concept))
    {}
    // must override copy constructor because of unique_ptr
    poly_thing(const poly_thing& r)
    : _impl(r._impl->clone())
    {}
    poly_thing(poly_thing&& r) = default;
    // must override copy constructor because of unique_ptr
    poly_thing& operator=(const poly_thing& r)
    {
        _impl = r._impl->clone();
        return *this;
    }
    poly_thing& operator=(poly_thing&& r) = default;
    //
    // here is our sane non-polymorphic interface.
    //        
    poly_thing operator++(int) {
        std::cout << "operator++(int)" << std::endl;
        auto clone_p = _impl->clone();
        _impl->increment();
        return poly_thing { std::move(clone_p) };
    }
    poly_thing& operator++() {
        std::cout << "operator++()" << std::endl;
        _impl->increment();
        return *this;
    }
    std::unique_ptr<concept> _impl;
};
// an implementation (model) of the concept
struct implementation_a : poly_thing::concept {
    std::unique_ptr<poly_thing::concept> clone() const override
    {
        std::cout << "cloning an a" << std::endl;
        return std::make_unique<implementation_a>(*this);
    }
    void increment() override {
        std::cout << "incrementing an a" << std::endl;
        // implementation here
    }
};
// a model derived from a model    
struct implementation_b : implementation_a {
    std::unique_ptr<poly_thing::concept> clone() const override
    {
        std::cout << "cloning a b" << std::endl;
        return std::make_unique<implementation_b>(*this);
    }
    // you can now choose whether to implement this
    void increment() override {
        // implementation here
        std::cout << "incrementing a b" << std::endl;
    }
};
// a small test
auto main() -> int
{
    poly_thing a(std::make_unique<implementation_a>());
    auto aa1 = a++;
    auto aa2 = ++a;
    poly_thing b(std::make_unique<implementation_b>());
    auto bb1 = b++;
    auto bb2 = ++b;
    return 0;
}
预期输出:

operator++(int)
cloning an a
incrementing an a
operator++()
incrementing an a
cloning an a
operator++(int)
cloning a b
incrementing a b
operator++()
incrementing a b
cloning a b

最新更新