【问题标题】:Incremental operator overload in an abstract class C++抽象类 C++ 中的增量运算符重载
【发布时间】:2016-05-20 18:20:09
【问题描述】:
#include <iostream>
using namespace std;

class A{
private:
  double price;
public:
  A(double p):price(p){
  }
  virtual double abstractExample() = 0;
  A* operator++(int dummy){
    this->price = this->price + 1;
    return this;
  }
  virtual ~A(){
  }
  void print(){
    cout << price << endl;
  }
};

class B : public A {
  public:
    B(int p): A(p){
    }
    double abstractExample(){
        return 1;
    }
};

int main(){
  B* b = new B(5);
  b->print();
  b++->print();

  return 0;
}

所以我有这个抽象类 A。我想重载 ++ 运算符。通常我只会写 A& operator ++(int dummy) 但在这种情况下我必须返回一个指向对象的指针,因为它是一个抽象类。有什么方法可以做到这一点,而无需在每个继承的类中编写单独的代码?

这给出了 5, 5 而不是 5, 6 的输入。

【问题讨论】:

  • 你实现的后缀运算符不正确,因为它应该返回值之前修改。
  • @SergeyA “你实现的后缀运算符不正确” 是的,没错。但是如何处理抽象类呢?这是个好问题。
  • @πάνταῥεῖ this 说尝试使用 CRTP
  • @πάνταῥεῖ,还记得“阅读后燃烧”吗?不要这样做。不要在抽象类上实现后缀增量,因为你不能真正实现它。
  • 注意:运算符与类的实例一起使用 - 而不是 (!) 与指向实例的指针一起使用!

标签: c++ overloading increment operator-keyword


【解决方案1】:

算术运算符不能很好地处理多态类,除非您将多态实现包装在非多态包装器中。

代码中的注释解释了对基类的添加:

#include <iostream>
#include <memory>

using namespace std;

class A{
private:
  double price;
public:
  A(double p):price(p){
  }
  virtual double abstractExample() = 0;

  void increment()
  {
    this->price = this->price + 1;
  }

  // see below. clone in base must be abstract if the base class
  // is abstract. (abstractExample is pure so that's that)
  virtual std::unique_ptr<A> clone() const =0;

  virtual ~A(){
  }

  void print(){
    cout << price << endl;
  }
};

class B : public A {
  public:
    B(int p): A(p){
    }
    double abstractExample(){
        return 1;
    }

  std::unique_ptr<A> clone() const override
  {
    return std::make_unique<B>(*this);
  }

};

struct AB 
{
  AB(std::unique_ptr<A> p) : _ptr(std::move(p)) {}

  // pre-increment is easy
  AB& operator++() {
    _ptr->increment();
  }

  // post-increment is trickier. it implies clonability.
  AB operator++(int) {
    AB tmp(_ptr->clone());
    _ptr->increment();
    return tmp;
  }

  void print() {
    _ptr->print();
  }

  std::unique_ptr<A> _ptr;
};

int main(){
  AB b(std::make_unique<B>(5));
  b.print();

  // pre-increment
  (++b).print();

  // post-incrememnt will involve a clone.
  (b++).print();

  return 0;
}

【讨论】:

    【解决方案2】:

    但在这种情况下,它必须返回一个指向对象的指针,因为它是一个抽象类。

    不,它没有。参考实际上更好。除非按值返回,否则不会遇到切片。

    【讨论】:

    • 只是后缀增量的实现不正确。
    • 也就是说,由于operator++返回的对象是this,你可以用*this安全地返回对this的引用,不会发生切片。返回的引用的生命周期是A-deriving 对象的生命周期。
    • @xxm0dxx 好吧,请注意返回引用可能会解决语法错误,但不会提供语义 POV 的预期行为。
    猜你喜欢
    • 2012-06-16
    • 1970-01-01
    • 2021-11-13
    • 1970-01-01
    • 2016-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-22
    相关资源
    最近更新 更多