Создание вектора пользовательского класса комплексных чисел с использованием std :: vector - PullRequest
1 голос
/ 10 июля 2020

Я новичок в программировании и в настоящее время изучаю C ++, чтобы начать работу, поэтому, пожалуйста, извините за мои узкие знания и очень возможные ошибки в коде и в целом C ++ lin go.

Я написал класс комплексных чисел называется ComplexNumber с переменными-членами double re и double im с очевидным значением. У этого класса есть конструктор, пустой конструктор, конструктор копирования, деструктор и т. Д. c.

Используя это, я хочу написать класс ComplexVector векторов с записями из ComplexNumber. На данный момент я определил переменные-члены как вектор std::vector<ComplexNumber> vec и размер int size. Кроме того, я хотел бы определить функцию-член void print(), опять же с очевидным смыслом. Код, который у меня есть до сих пор:

#include <iostream>
#include <vector>

#include "complex.h"

class ComplexVector {
  private:
    std::vector<ComplexNumber> vec;
    int size;

  public:
    ComplexVector(std::vector<ComplexNumber> vector, int n){ //constructor
      size = n;
      vec = vector;
    };
    ComplexVector(){ //empty constructor
      size = 0;
      vec = {};
    };
    void print() const;
    ~ComplexVector(); //destructor
    ComplexVector(const ComplexVector& v); //copy constructor
    ComplexVector addition(ComplexVector w);      //
    ComplexVector subtraction(ComplexVector w);   // i am not worrying about these for now
    ComplexVector scale(ComplexNumber z);         //
};

с определениями

void ComplexVector::print() const {
  for(std::vector<ComplexNumber>::iterator it = vec.begin(); it != vec.end(); it++){
    std::cout << *it << " ";
  };
  std::cout << std::endl;
};

ComplexVector::~ComplexVector(){
  std::cout << "calling destructor" << std::endl;
};

ComplexVector::ComplexVector(const ComplexVector& v){
  size = v.size;
  vec = v.vec;
};

Вот где я получаю ошибку компиляции: в определении print мой компилятор сообщает мне

error: no viable conversion from '__wrap_iter<std::__1::vector<ComplexNumber, std::__1::allocator<ComplexNumber>
      >::const_pointer>' to '__wrap_iter<std::__1::vector<ComplexNumber, std::__1::allocator<ComplexNumber> >::pointer>'
  for(std::vector<ComplexNumber>::iterator it = vec.begin(); it != vec.end(); it++){

, с которыми я не совсем уверен, что делать. Я кое-что читал о некоторых функциях-членах, которые необходимо определить для ComplexNumber, которые будут использоваться в std::vector. Я также поигрался с определением итераторов внутри ComplexVector, но это не решило проблему. С моей (честно говоря, очень узкой) точки зрения должен быть итератор для vec, а также для соответствующих функций begin() и end(). Я тысячу раз проверял, передаю ли я аргументы правильного типа, но, должно быть, что-то не замечаю.

Еще одна вещь, на которую следует обратить внимание: я очень хорошо понимаю, что это, вероятно, крайне неэффективный способ определите такой класс. Я просмотрел несколько примеров, в которых указатели на массив использовались в качестве основной переменной-члена. Я обязательно собираюсь реализовать что-то в этом роде в следующий раз, но пока я хочу понять, где ошибка в моем текущем коде. Так что заранее спасибо за любые ответы.

Один побочный вопрос: я не думаю, что я очень хорошо понял концепцию деструктора (честно говоря, я еще не провел много времени, читая об этом), но если у кого-то есть быстрая интуиция о них, которой он / она хочет поделиться, это было бы очень признательно.

Также, если у вас есть какие-либо комментарии по стилю и / или другим улучшениям моего кода, я был бы признателен это, если бы вы могли поделиться ими.

Спасибо!

Изменить: вот ComplexNumber класс

class ComplexNumber {
  private:
    double re;
    double im;
  public:
    ComplexNumber(double x, double y){
      re = x;
      im = y;
    };
    ComplexNumber(){
      re = im = 0;
    };
    ComplexNumber(const ComplexNumber& z);
    void print() const;
};

и определения

void ComplexNumber::print() const {
    if(im > 0){
      std::cout << re << "+" << im << "i" << std::endl;
    } else if(im < 0){
      std::cout << re << im << "i" << std::endl;
    } else {
      std::cout << re << std::endl;
    };
};

ComplexNumber::ComplexNumber(const ComplexNumber& z){
  re = z.re;
  im = z.im;
};

И основной способ:

int main() {

  std::vector<ComplexNumber> v1 = {ComplexNumber(1,2), ComplexNumber(4,2)};
  int n = 2;
  ComplexVector w1(v1,n);
  w1.print();

  return 0;
}

1 Ответ

2 голосов
/ 10 июля 2020

Ваша проблема здесь:

void ComplexVector::print() const {
  for(std::vector<ComplexNumber>::iterator it = vec.begin(); it != vec.end(); it++){
    std::cout << *it << " ";
  };
  std::cout << std::endl;
};

Обратите внимание, что функция отмечена const. Это означает, что любые члены класса рассматриваются как константы, квалифицированные внутри метода (т.е. вам не разрешено изменять их). Таким образом, когда вы вызываете vec.begin(), вы вызываете константную версию begin() для вектора. Это возвращает const_iterator, а не iterator.

  std::vector<ComplexNumber>::iterator it = vec.begin()
                              ^^^^^^^^ should be const_iterator

Лучший способ решить эту проблему - использовать auto и позволить компилятору определить правильный тип:

   auto it = vec.begin()

Таким образом, функция становится:

void ComplexVector::print() const {
  for(std::vector<ComplexNumber>::const_iterator it = vec.begin(); it != vec.end(); it++){
    std::cout << *it << " ";
  };
  std::cout << std::endl;
}

или с авто:

void ComplexVector::print() const {
  for(auto it = vec.begin(); it != vec.end(); it++){
    std::cout << *it << " ";
  };
  std::cout << std::endl;
}

, или вы можете улучшить это, используя новую версию for()

void ComplexVector::print() const {
  for(auto const& item: vec){
    std::cout << item << " ";
  };
  std::cout << "\n";
}

Примечание: когда ваш код работает. Вы можете запросить отзыв о стиле по телефону https://codereview.stackexchange.com

Дальнейшие действия на основе комментариев: Попробуйте:

class ComplexNumber
{
     ...... 
     friend std::ostream& operator<<(std::ostream& str, ComplexNumber const& data) {
         data.print(); // You want to change this
                      // so you can pass the stream to print.
         return str;
     }
}
...