【问题标题】:Creating vector of custom complex number class using std::vector使用 std::vector 创建自定义复数类的向量
【发布时间】:2020-07-09 22:37:31
【问题描述】:

我是编码新手,目前正在学习 C++ 入门,所以请原谅我的狭隘知识以及代码和一般 C++ 术语中很可能出现的错误。

我写了一个名为ComplexNumber的复数类,其成员变量为double redouble im,含义很明显。该类有构造函数、空构造函数、复制构造函数、析构函数等。

使用它,我现在的意思是编写一个向量类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() 函数。我已经检查过我是否传递了正确类型的参数一千次,但我肯定忽略了一些东西。

还有一点需要注意的是,我非常清楚这可能是一种非常低效的方式来定义这样的类。我查看了多个使用指向数组的指针作为主要成员变量的示例。接下来我肯定会实现这种类型的东西,但现在我想了解我当前代码中的错误在哪里。所以提前感谢任何答案。

一个问题:我认为我不太了解析构函数的概念(公平地说,我还没有花太多时间阅读它),但如果有人对它们有一个快速的直觉,那就是他/她想分享,我们将不胜感激。

另外,如果您对我的代码的样式和/或其他改进有任何 cmet,如果您能分享它们,我将不胜感激。

谢谢!

编辑:这是ComplexNumberclass

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

【问题讨论】:

  • 你的类中不需要size 成员变量。只需使用vector::size()。析构函数也一样——不需要。
  • 您显示的代码不是您实际编译的代码。错误消息提到了std::list&lt;ComplexNumber&gt;::iterator,它没有出现在显示的代码中。
  • tl;博士;您介意创建minimal reproducible example 并解释其用途吗?
  • 让它for (const auto&amp; number: vec) { std::cout &lt;&lt; number &lt;&lt; " "; };
  • 关于size 成员,目前可以像ComplexVector(std::vector&lt;ComplexNumber&gt;{x, y, z}, 10000) 这样调用您的代码,这显然是错误的。 std::vector 已经跟踪自己的大小,无需创建歧义和浪费空间。

标签: c++ arrays c++11 vector iterator


【解决方案1】:

你的问题在这里:

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

请注意,该函数标记为const。这意味着该类的任何成员都被视为方法内的 const 限定(即,您不得修改它们)。因此,当您调用 vec.begin() 时,您正在调用向量上的 begin() 的 const 版本。这将返回 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 要求对风格进行评论


基于cmets的跟进: 试试:

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

【讨论】:

  • 非常感谢,但由于某种原因,即使我调整了代码,我也会在打印*it 的行中收到invalid operands to binary expression 错误,这通常不会发生,当有人不小心尝试时“打印”声明为函数的东西?
  • 这意味着它不知道如何打印复数类型的 const 版本。查看 operator&lt;&lt;() 的复杂类型(看起来你甚至没有,所以你可能需要添加它)看看它是否通过 const 引用获取参数。
  • @thore。请参阅我刚刚添加到答案末尾的添加内容。
  • 非常感谢;这完美地工作。我会确保阅读这些运算符:)
  • @thore 现在可以在这里得到适当的评价:codereview.stackexchange.com
猜你喜欢
  • 1970-01-01
  • 2020-10-05
  • 2019-09-07
  • 1970-01-01
  • 1970-01-01
  • 2020-10-17
  • 2011-10-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多