1

我正在尝试创建我自己版本的名为 safearray 的数组,以测试我对运算符重载和创建适当类等的知识。

我遇到两个错误。

SafeArray.h:11:15:错误:'const int SafeArray::operator' 不能重载

SafeArray.h:10:10: 错误: with 'int& SafeArray::operator'</p>

我的代码分为三个文件。

主文件

#include <cstdlib>
#include <iostream>

#include "SafeArray.h"

using namespace std;

int main(int argc, char** argv) {

    SafeArray a(10); // 10 integer elements

    for (int i = 0; i < a.length(); i++) {
        cout << i << " " << a[i] << "s" << endl; // values initialise to 0
    }

    cout << endl << a[1]; // Program exits here.

    a[3] = 42;
    cout << a[3];
    a[10] = 10;
    cout << a[10];
    a[-1] = -1; // out-of-bounds is "safe"?

    SafeArray b(20); // another array

    b = a; // array assignment

    for (int i = 0; i < b.length(); i++) {
        cout << b[i] << endl; // values copied from a
    }

    return 0;
}

安全阵列.h

#ifndef SAFEARRAY_H
#define SAFEARRAY_H

class SafeArray {
public:
    SafeArray(int);              // int variable will be the array size
    int length();
    int boundsCheck(int y);       // constructor will call this function
//    const SafeArray operator= (const SafeArray&);
    int& operator[] (int y);
    const int operator [] (const int y); // you need this one too.

    SafeArray &operator=(SafeArray rhs) { 
    std::swap(array, rhs.array);
    std::swap(length_, rhs.length_);
        }

    SafeArray(SafeArray const &other);
    ~SafeArray();
private:
    int length_;
    int *array;
    //int array[];
};

#endif  /* SAFEARRAY_H */

安全阵列.cpp

#include "SafeArray.h"
#include <iostream>

SafeArray::SafeArray(int x) {
    length_ = x;
    array = new int[length];
    for (int i = 0; i < length_; i++) {
        array[i] = 0;
    }
}

int SafeArray::length() {
    return this->length_;
}

int SafeArray::boundsCheck(int y) {

}

int& SafeArray::operator[] (int y) {
    return array[y];
}

SafeArray::~SafeArray() { 
    delete [] array;
}

SafeArray::SafeArray(SafeArray const &other) { 
    int *temp = new int[rhs.size_];
    for (int i=0; i<rhs.size_; i++)
        temp[i] = rhs.array[i];
    std::swap(temp, array);
    delete [] temp;
    return *this;
}
4

4 回答 4

3

您的类定义无效。int array[]是一个不完整的类型,它不能作为(非静态)类成员出现。一些编译器接受它作为 的同义词int array[0],但零大小的数组在 C++ 中也无效(仅在 C99 中)。

简而言之,您不能按照自己的方式编写代码。您需要了解动态分配并管理自己的内存。看看是如何std::vector实现的。

在 C++11 中,我可能会推荐一种std::unique_ptr<int[]> array快速修复方法,将其初始化为array(new int[x]).

于 2012-04-03T23:43:36.697 回答
0

错误消息指的是这两行:

int& operator[] (int y);
const int operator [] (const int y); // you need this one too.

您的错误消息说 (int y) 和 (const int y) 太相似了,不能成为 [] 运算符的两个不同重载。您不能在 (int y) 和 (const int y) 上重载,因为调用都是模棱两可的。

如果您的 SafeArray 是 const,您可能打算返回一个 const int,但如果您的 SafeArray 不是 const,则返回一个 int&。在这种情况下,您可以通过将单词 const 放在参数列表之后来声明要应用于 const SafeArray 的第二个函数。这是您应该在 SafeArray.h 中编写的内容:

int& operator[] (int y);
const int operator [] (int y) const; // you need this one too.

然后,您必须在 SafeArray.cpp 中编写这两个函数:

int& SafeArray::operator[] (int y) {
    return array[y];
}

const int SafeArray::operator[] (int y) const { // you need this one too.
    return array[y];
}
于 2014-11-14T22:37:38.667 回答
0

实际上 int array[] 是有效的,并且可能作为类成员出现。以下以严格的 C++11 一致性编译:

class foo 
{
public:
    foo() {}
    int length;
    int A[];
};

void ralph()
{
    foo *bar = (foo *)new int[ 21 ];
    bar->length = 20;
    bar->A[0] = 1;
}

这是合法的,并且有其优势(偶尔)。虽然不常用。

但是,我怀疑 OP 想要更多类似的东西

class SafeArray {
public:
    SafeArray(int);              // int variable will be the array size
    int length();
    int boundsCheck(int y);       // constructor will call this function

    int& operator[] (int y);
    const int operator [] (const int y) // you need this one too.
private:
    int length_;
    int *array;
};

随着

SafeArray::SafeArray(int x) {
    length_ = x;
    array = new int[length];
    for (int i = 0; i < length_; i++) {
        array[i] = 0;
    }
}
于 2012-04-04T00:04:49.407 回答
0

正如@Kerrek 已经指出的那样,您的类定义显然是错误的(不应该编译)。

要修复它,您需要将定义更改为:

int *array;

然后在你的默认ctor中你可以使用这样的东西:

SafeArray::SafeArray(unsigned size = 0) 
    : array(new int[size])
{ 
    for (unsigned i=0; i<size; i++)
        array[i] = 0;
}

然后,是的,您需要编写一个赋值运算符。通常的方式称为复制和交换习语。您创建一个副本,然后将当前副本的内容与副本的内容交换:

SafeArray &operator=(SafeArray rhs) { 
    std::swap(array, rhs.array);
    std::swap(length_, rhs.length_);
}

除此之外,您还需要一个复制构造函数来复制数据:

SafeArray::SafeArray(SafeArray const &other) { 
    int *temp = new int[rhs.size_];
    for (int i=0; i<rhs.size_; i++)
        temp[i] = rhs.array[i];
    std::swap(temp, array);
    delete [] temp;
    return *this;
}

最后,您需要一个析构函数来销毁一个对象并(特别是)删除它所拥有的内存:

SafeArray::~SafeArray() { 
    delete [] array;
}

然后意识到所有这些都是一个丑陋的烂摊子,永远不会真正运作良好。特别是,基本方法仅限于大小基本固定的数组。只要您只存储ints,就很容易忽略这些问题,并制作一个(有点)有效的动态数组。但是,当/如果您想存储其他类型时,您只需将分配内存与初始化该内存中的对象分开,这意味着基本上丢弃上面的所有代码,并将其替换为:

  1. 分别跟踪数组大小和分配大小
  2. ::operator new使用、 Allocator 对象或其他类似对象分配内存
  3. 需要时使用placement new 来初始化内存中的对象。
  4. 使用显式析构函数调用来销毁对象
  5. 用于::operator delete释放内存

等等。总而言之,std::vector不是一件微不足道的工作。

于 2012-04-04T00:05:27.497 回答