简体   繁体   English

带有抽象继承的后缀运算符++

[英]postfix operator++ with abstract inheritance

I want to implement prefix and postfix operator++ in a struct hierarchy (abstract base A and child B). 我想在结构层次结构(抽象基数A和子B)中实现前缀和后缀运算符++。 When only implementing prefix in base class, this works fine. 当只在基类中实现前缀时,这很好。 However, when implementing the postfix version in the child class (since it cannot be implemented in an abstract class) it doesn't work. 但是,在子类中实现后缀版本时(因为它不能在抽象类中实现),它不起作用。

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

The thing is that I want to avoid repeating code and since all derived classes will use operator++ in the same way, it would be best to not implement them all in their respective classes. 问题是我想避免重复代码,因为所有派生类都将以相同的方式使用operator ++,所以最好不要在各自的类中实现它们。 The whole point of using the abstract class was to avoid this! 使用抽象类的重点是避免这种情况!

My question is: what is the most elegant way to solve this? 我的问题是:解决这个问题最优雅的方法是什么?

EDIT. 编辑。 Error message: cannot increment value of type 'B' 错误消息:无法递增类型'B'的值

The problem is that the operator++ in the derived class is hiding the name in the base class. 问题是派生类中的operator++将名称隐藏在基类中。 Try adding the following to B : 尝试将以下内容添加到B

using A::operator++;

You may find it difficult to make the post-increment function behave polymorphically though. 您可能会发现很难使后增量函数具有多态性。 Covariant return types will not work. 协变返回类型不起作用。

Live demo. 现场演示。

Since you ask for a more elegant way to do this, my view is that the most elegant way is to hide the details of the polymorphic interface from consumers of your class as much as possible. 由于您要求更优雅的方法来实现这一点,我的观点是最优雅的方法是尽可能地隐藏类的消费者的多态接口的细节。

One more class to contain your polymorphic concept will do the trick, and allow you to implement post-increment easily and safely: 包含多态概念的另一个类可以解决这个问题,并允许您轻松安全地实现后增量:

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

expected output: 预期产量:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何调用后缀运算符++? - How to call postfix operator++? 如何在抽象 class 中声明 operator++(int)? - How to declare operator++(int) in an abstract class? 为什么postfix operator ++的优先级高于前缀operator ++? - Why does postfix operator++ have higher precedence than prefix operator++? 如何以两种不同的方式为后缀 a++ 和前缀 ++a 重载运算符++? - How to overload the operator++ in two different ways for postfix a++ and prefix ++a? std :: atomic error:没有'operator ++(int)'声明为postfix'++'[-fpermissive] - std::atomic error: no ‘operator++(int)’ declared for postfix ‘++’ [-fpermissive] 相互重载operator ++前缀/后缀? - Overloading operator++ prefix / postfix in terms of each other? C++ 编译器如何扩展前缀和后缀运算符 ++()? - How does a C++ compiler expand prefix and postfix operator++()? 作为后缀和前缀的operator ++不适用于clang - operator++ as both a postfix and prefix doesn't work with clang operator ++(int)重载与抽象基类和Wall - operator++(int) overload with abstract base class and Wall 错误:后缀&#39;unaryOperators unaryOperators :: operator ++(const unaryOperators&)&#39;必须以&#39;int&#39;作为参数 - error: postfix ‘unaryOperators unaryOperators::operator++(const unaryOperators&)’ must take ‘int’ as its argument
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM