实现一个数组类,功课麻烦

时间:2013-11-18 08:43:38

标签: c++ arrays

正如标题所说,我的任务的一部分是实现一个数组类。教授为我们提供了标题样式,为我们创建了函数声明。使用前面的例子,我已经尽力定义这些函数,但是我在理解正在发生的事情时遇到了很多麻烦。发布整个头文件可能有点多,但我会尝试解释我遇到的问题。这是我的代码:

#ifndef ARRAY_H
#define ARRAY_H
#include <iostream>
#include <string>
using namespace std;

template <class T>
class Array {
private:
    int size;
    T * arr;
public:
    int getSize();

    Array();
    Array(int size);
    Array(Array & other);
    Array(T[], int n);
    ~Array();
    Array & operator=(Array & rhs);
    Array & operator+(Array & rhs); // append
    T & operator[](int i); //allow read and write
    const T & operator[](int n) const; // readonly
    void print(int n = 5);
    void print(ostream & out, int n);
    operator int *() { return arr; }
    friend ostream & operator <<(ostream & out, Array <T>& rhs);
};

template <class T>
int Array<T>::getSize() {
    return size;
}

template <class T>
Array<T>::Array() {
    arr = new T[];
}

template <class T>
Array<T>::Array(int size) {
    arr = new T[size];
}

template <class T>
Array<T>::Array(Array & other) {
    size = other.getSize();
    arr = new T[size];
    copy(arr[0], arr[size + 1], other.arr[0]);
}

template <class T>
Array<T>::Array(T[], int n) {
    size = n;
    arr = new T[n];
}

template <class T>
Array<T>::~Array() {
    if (arr) {
        delete arr;
    }
}

template <class T>
Array<T>& Array<T>::operator=(Array & rhs) {
    if (this != &rhs) {
        delete[] arr;
        size = rhs.getSize();
        arr = new T[size];
        copy(arr[0], arr[size+1], rhs.arr[0]);
    }
    return *this;
}

template <class T>
Array<T>& Array<T>::operator+(Array & rhs) {
    Array *tmp;

    tmp = new Array(size + rhs.getSize());
    return *tmp;
}

template <class T>
T& Array<T>::operator[](int i) {
    assert(0 <= i && i < size);
    return arr[i];
}

template <class T>
const T& Array<T>::operator[] (int n) const {
    assert(0 <= i && i < size);
    return arr[i];
}

template <class T>
void Array<T>::print(ostream &out, int n) {
    for (size_t i = 0; i < n; i++) {
        out << arr[i] << " ";
    }
}

template <class T>
void Array<T>::print(int n = 5) {
     print(cout, n);
}

template <class T>
ostream & operator << (ostream & out, Array<T> & rhs) {
    out << "( " << rhs.getSize() << ")";
    return out;
}

#endif

我会感谢任何和所有的提示,只是为了帮助我弄清楚这堂课里发生了什么。如果这最终要求很多,我很抱歉。

编辑:再次感谢大家的帮助!链接器错误是固定的。我应该指明印刷品是班级的成员,而不仅仅是自由。

1 个答案:

答案 0 :(得分:2)

  
      
  1. 在第46行尝试为Array(Array & other);执行复制构造时,我收到错误error C2664: 'char *strcpy(char *,const char *)' : cannot convert argument 1 from 'int *' to 'char *'它一直指向strcpy函数,但我不确定是什么它要我改变。我在同一行中遇到两个错误,第二个错误表示cannot convert argument 1 from 'std::string *' to 'char *'
  2.   

这里的问题是strcpy意味着在两个内存位置之间复制char类型。但是,您的模板参数T可以是任何类型,因此,如果您需要通用性,那么在此使用strcpy是不合适的。复制构造函数的直接(但不是非常有效)实现类似于:

template <class T>
Array<T>::Array(const Array &other) : size(other.size), arr(new T[size])
{
  for (int i = 0; i < size; ++i)
    arr[i] = other.arr[i];
}
  

2)在编写strcpy overloader时,我在第71行尝试operator=函数时遇到另一个错误。它告诉我cannot convert argument 1 from 'std::string *' to 'char *'

同样,它与一个问题相同:较旧的C风格str*函数使用原始char *指针指向包含字符的一些内存块。因此,这些函数组不能直接使用标准c ++库中的std::string,而无需进行一些调整。大多数情况下,您不想这样做,因为这些函数可以在不保留其内部不变量的情况下变异std::string

对于赋值运算符,您只需执行复制和交换:

template <class T>
Array<T>& Array<T>::operator = (Array rhs)
{
  std::swap(size, rhs.size);
  std::swap(arr, rhs.arr);
  return *this;
}
  

3)对于第85行的T & operator[](int i); //allow read and write,我想知道我是否应该创建一个包含i个广告位的新数组。教授留下的允许,阅读和写评论使我感到困惑。另外,对于以下函数,Array<T>::T & operator[] (int n) const;注释只读,所以我假设我应该用n项返回数组。

operator []用于提供语法糖,以便在给定某个索引Array<T>时访问i中的特定项目。如果没有它,以下将无法运作:

Array<int> arr(42);
std::cout << arr[0];

因此,您不必在此运算符内分配任何内容。您可以以相同的方式实现const和非const版本。唯一不同的是,最后会有一个const限定符,因此这也适用于const Array<T>

template <class T>
T& Array<T>::operator[] (int i) 
{
  assert(0 <= i && i < size);
  return arr[i];
}

template <class T>
const T& Array<T>::operator[] (int i) const
{
  assert(0 <= i && i < size);
  return arr[i];
}
  

4)我留下了对void print(int n = 5);函数的评论。但总而言之,我希望每行能够在数组中打印出一定数量的项目,但是没有多维数组。我尝试了两个for循环,但它只是卡在同一个数组项上。

     

5)我不确定为什么需要void print(ostream & out, int n);。它应该覆盖上面的print语句吗?

您正在寻找的正确术语是&#34;重载&#34;。 &#34;覆盖&#34;在C ++命名法中有一个非常具体的含义,在这种情况下并不适用。

从声明来看,似乎第二个print签名的意图是支持不同类型的输出流(其中cout是一种类型的btw)。您要做的是在第二个版本中实现print的第一个版本。事实上,他们根本不需要成为模板功能:

void print(ostream &out, int n)
{
  for (size_t i = 0; i < n; ++i)
    out << pets[i] << " ";
}

void print(int n)
{
  print(cout, n);
}

注意,应该修改print以使数组打印出来而不是在这里引用一个(全局?)特定实例。

修改:修改print以使阵列打印时,当然必须是模板。一个可能的签名:

  template <typename T>
  void print(const Array<T> &arr, int n)
  {
    print(arr, n, cout);
  }