C ++运算符重载 - '重新创建Vector'

时间:2010-04-02 16:26:45

标签: c++ operator-overloading

我目前正处于拼贴二级编程课程......我们正在研究运算符重载...要做到这一点,我们要重建矢量类... 我正在构建课程,发现其中大部分是基于[] operator。当我试图实现+ operator时,我遇到了一个奇怪的错误,我的教授之前没有见过(显然是因为班级将IDE从MinGW切换到VS表达...)(我使用的是Visual Studio Express 2008 C ++版...)

Vector.h

#include <string>
#include <iostream>
using namespace std;

#ifndef _VECTOR_H
#define _VECTOR_H

const int DEFAULT_VECTOR_SIZE = 5;

class Vector
{
private:
    int *   data;
    int     size;
    int     comp;
public:
    inline  Vector      (int Comp = 5,int Size = 0) 
        : comp(Comp), size(Size)    { if (comp > 0) { data = new int [comp]; } 
                                      else { data = new int [DEFAULT_VECTOR_SIZE];
                                      comp = DEFAULT_VECTOR_SIZE; }
                                    }
    int      size_      ()          const       { return size; }
    int      comp_      ()          const       { return comp; }
    bool     push_back  (int);
    bool     push_front (int);
    void     expand     ();
    void     expand     (int);
    void     clear      ();
    const    string at  (int);
    int&         operator[ ](int);
    int&         operator[ ](int) const;
    Vector&  operator+  (Vector&);
    Vector&  operator-  (const Vector&);
    bool     operator== (const Vector&);
    bool     operator!= (const Vector&);

    ~Vector() { delete [] data; }
};

ostream& operator<< (ostream&, const Vector&);

#endif

Vector.cpp

#include <iostream>
#include <string>
#include "Vector.h"
using namespace std;

const string Vector::at(int i) {
    this[i];
}

void Vector::expand() {
    expand(size);
}

void Vector::expand(int n ) {
    int * newdata = new int [comp * 2];
    if (*data != NULL) {
        for (int i = 0; i <= (comp); i++) {
            newdata[i] = data[i];
        }
        newdata -= comp;
        comp += n;
        data = newdata;
    delete newdata;
    }
    else if ( *data == NULL || comp == 0) {
        data = new int [DEFAULT_VECTOR_SIZE];
        comp = DEFAULT_VECTOR_SIZE;
        size = 0;
    }
}

bool Vector::push_back(int n) {
    if (comp = 0) { expand(); }
    for (int k = 0; k != 2; k++) {
        if ( size != comp ){
            data[size] = n;
            size++;
            return true;
        }
        else {
            expand();
        }
    }
    return false;
}

void Vector::clear() {
    delete [] data;
    comp = 0;
    size = 0;
}
int& Vector::operator[] (int place) { return (data[place]); }
int& Vector::operator[] (int place) const { return (data[place]); }

Vector& Vector::operator+ (Vector& n) {
    int temp_int = 0;

    if (size > n.size_() || size == n.size_()) { temp_int = size; }
    else if (size < n.size_()) { temp_int = n.size_();  }

    Vector newone(temp_int);
    int temp_2_int = 0;

    for ( int j = 0; j <= temp_int && 
                     j <= n.size_() && 
                     j <= size; 
                                        j++) {
        temp_2_int = n[j] + data[j];
        newone[j] = temp_2_int;
    }
////////////////////////////////////////////////////////////
    return newone;
////////////////////////////////////////////////////////////
}

ostream& operator<< (ostream& out, const Vector& n) {
    for (int i = 0; i <= n.size_(); i++) {
////////////////////////////////////////////////////////////
        out << n[i] << " ";
////////////////////////////////////////////////////////////
    }
    return out;
}

错误:

out << n[i] << " "; error C2678:

binary'[':没有运算符找到哪个 采用类型的左手操作数 'const Vector'(或者没有 可接受的转换)

return newone;

错误C2106:'=':左 操作数必须是l值


如上所述,我是一名从事计算机科学的学生,因为我选择了专业,我会很感激提示,指针以及更好的方法:D

6 个答案:

答案 0 :(得分:10)

此:

int operator[ ](int);

是非const成员函数。这意味着无法在const Vector上调用它。

通常,下标运算符被实现为返回一个引用(如果你返回一个值,就像你正在做的那样,你不能将它用作左值,例如你不能像newone[j] = temp_2_int;那样你有代码):

int& operator[](int);

为了能够在const对象上调用它,您还应该提供成员函数的const版本:

const int& operator[](int) const;

因为你要求“提示,指示和更好的方法来做事:”

  • 您无法为包含守卫_VECTOR_H命名。以下划线后跟大写字母开头的名称将保留用于实现。有a lot of rules about underscores
  • 永远不会在标题中使用using namespace std
  • 您的operator+应该选择const Vector&,因为它不会修改其论点。
  • 您的at应返回int并且应该与C ++标准库容器的语义匹配(即,如果i超出范围,它应该抛出异常。您需要使用(*this)[i]来调用重载的operator[]
  • 您需要了解*运算符的作用。在一些地方,你混淆了指针和它们指向的对象。
  • 注意===混淆(例如在if (comp = 0)中)。编译器警告您。不要忽视警告。
  • 如果您保证data永远不会为NULL,那么您的逻辑会更简单。

答案 1 :(得分:2)

除了其他人已经写过的关于你operator[]()

的内容

您的operator+()根据非const引用采取右侧 - 就像它会尝试更改它一样。但是,对于A+B,每个人都希望B保持不变。

此外,我将实现所有二元运算符同等地处理它们的操作数(即,不改变它们中的任何一个)作为非成员函数。作为成员函数,左侧(this)可以区别对待。 (例如,它可能会在派生类中受到覆盖版本的影响。)

然后,IME始终将operator+()基于operator+=()operator+=()不会平等对待它的操作数(它改变了左边的操作数),因此最好将其作为成员函数来完成。完成后,在它上面实现operator+()是件小事。

最后,operator+()永远不应该永远不会返回对象的引用。当你说A+B时,你希望它返回一个新对象,而不是更改一些现有对象并返回对它的引用。

答案 2 :(得分:2)

不能将此纳入对Neil答案的评论中,所以我将在这里详细介绍。

关于expand()功能。看起来这个函数的工作是扩展内部存储,其中包含comp元素,n个元素,同时保持Vector的size。那么让我们来看看你拥有的东西。

void Vector::expand(int n) {
    int * newdata = new int [comp * 2];

好的,你刚刚创建了一个比旧版本大两倍的新数组。错误:为什么新尺寸与n没有任何关系?

    if (*data != NULL) {

错误:*data是数组中的第一个int元素。它不是指针。为什么要将其与NULL进行比较?

概念错误:即使你说if (data != NULL),这可能是一个测试,看看是否有一个数组,data设置为NULL的时间点new []NULL如果内存不足,则不会返回 for (int i = 0; i <= (comp); i++) { newdata[i] = data[i]; } ;它引发了异常。

size

警告:您正在复制整个数组,但只有第一个size元素有效。该循环可能只能运行到 newdata -= comp; ,你就可以了。

newdata

错误:指针数学错误。 comp设置为指向谁知道从int开始的newdata delete []返回的位置的指针?!),几乎可以肯定是一个会损坏内存的指针给 comp += n;

        data = newdata;
        delete newdata;
    }

这很好,因为它是什么。

    else if ( *data == NULL || comp == 0) {
        data = new int [DEFAULT_VECTOR_SIZE];
        comp = DEFAULT_VECTOR_SIZE;
        size = 0;
    }
}

错误:您存储了一个指针,然后立即删除了它的内存,使其成为无效指针。

data

错误:这应该在你的构造函数中,而不是在这里。同样,没有任何内容将NULL设置为*dataintcomp + n,而不是指针。

这个函数应该做什么:

  • 创建一个新的size元素数组
  • 将旧数组中的data元素复制到新数组
  • 删除旧数组
  • 将{{1}}设置为指向新数组
祝你好运。

答案 3 :(得分:1)

您需要提供两个版本的operator []。访问:

T operator[](std::size_t idx)const;

写入元素:

T& operator[](std::size_t idx);

在上述两种情况中,将T替换为元素的类型。你遇到这个问题的原因是只能在声明为“const”的对象上调用标记为“const”的函数。将所有非变异函数标记为“const”绝对是您应该做的事情,称为“const-correctness”。由于返回对元素的引用(写入所必需)允许底层对象被突变,因此该函数的版本不能被设为“const”。因此,需要只读“const”重载。

您可能也有兴趣阅读:

答案 4 :(得分:1)

您的代码中存在很多错误,因此很难知道从哪里开始。这是一个:

 delete [] data;
 *data = *newdata;

删除指针,然后立即取消引用它。

const string Vector::at(int i) {
    this[i];
}

这是(我认为)一个整数的向量。为什么这会返回一个字符串?将[]运算符应用于此不会调用运算符[]重载 - 它将此视为数组,而不是。

答案 5 :(得分:0)

int Vector::operator[] (int place) { return (data[place]); }

这应该是

int Vector::operator[] (int place) const { return (data[place]); }

这样您就可以对const向量执行[]操作。函数声明后的const表示类实例(this)被视为const Vector,这意味着您将无法修改常规属性。或者换句话说:一种只具有对属性的读访问权的方法。