Можем ли мы объявить абстрактный метод для возврата объектов подкласса в абстрактный суперкласс без новой реализации? - PullRequest
1 голос
/ 03 ноября 2019

Я хочу создать класс (например, VectorSpace), который будет иметь определенные методы, абстрактно представленные в классе. Я недавно перешел с Java на c ++, и я нахожу проблемы при попытке перефразировать объявление общего абстрактного метода в java

Ситуация такова, что c ++ не допускает объявление, такое как:AbstractClass methodName (...) = 0;Java, с другой стороны, позволяет возвращаемому типу быть абстрактным классом. Это не разрешено в c ++, и компиляция приводит к ошибке, говорящей, что абстрактный класс не может действовать как тип возврата для метода. Я прошел через эту страницу: возвращает абстрактный класс из функции . Поэтому в c ++ я сделал следующее:

//Fields are any classes which +,* defined on them
  template<class F> class VectorSpace
  {
    virtual VectorSpace<F>* operator+(const VectorSpace<F>& el) const =0;
    virtual VectorSpace<F>* operator-() const =0;
    virtual VectorSpace<F>* operator*(const F& el) const =0;
    ....
  };
  class Vector : public VectorSpace<double>
  {
      ....
      Vector* operator+(const VectorSpace<double>& el) const {return new Vector(....);}
  }

Однако проблема с этим будет в том, что я буду использовать «new» для создания экземпляра объекта для любого класса, который является подклассом VectorSpace (например, Vector) всякий раз, когда применяются какие-либо операторы (например, +, -), которые необходимо будет удалить вручную.

Есть ли способ обойти это?

1 Ответ

0 голосов
/ 03 ноября 2019

Вы можете иметь другой класс, скажем, VectorWrapper, который оборачивает указатель на абстрактный класс, например, через std::unique_ptr<VectorSpace<double> >. В этом классе вы можете перегрузить operator+, чтобы перенаправить вызов в реализацию, а затем вернуть новую локально созданную оболочку. Удаление std::unique_ptr исключает ручное удаление, и у вас перегружены операторы, которые возвращают по значению, поэтому они просты в использовании. Обратите внимание, что операторы new и delete по-прежнему вызываются изнутри и инкапсулируются VectorWrapper.

class VectorWrapper 
{
    VectorWrapper(std::unique_ptr<VectorSpace<double> > ptr)
        : m_impl(std::move(ptr))
    {}
    VectorWrapper operator+(const VectorWrapper& other)
    {
         return VectorWrapper(*m_impl + *other.m_impl);
    }
private:
    std::unique_ptr<VectorSpace<double> > m_impl;
};

Это тесно связано с идиомой стирания типа C ++.

Редактировать: также вы 'Вам нужно будет реализовать конструктор копирования и присваивание для вызова std::make_unique и т. д. Или, если векторы неизменны - как и математические объекты - вы можете рассмотреть возможность использования std::shared_ptr, но это может быть даже медленнее, в зависимости от того, как часто VectorWrapperскопировано в ваш код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...