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

发布于 2024-08-27 08:06:13 字数 3925 浏览 6 评论 0原文

我目前正在学习拼贴二级编程课程...我们正在研究运算符重载...为此,我们将重建向量类... 我正在构建该类,发现它的大部分都是基于 [] 运算符。当我尝试实现 + 运算符时,我遇到了一个奇怪的错误,这是我的教授以前从未见过的(显然是因为课程将 IDE 从 MinGW 切换到 VS Express...)(我正在使用 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:

二进制“[”:找不到哪个运算符 接受类型的左操作数 'const Vector'(或者没有 可接受的转换)

return newone;

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


如上所述,我是一名学生,正在选择计算机科学作为我选择的专业,我希望得到提示、指示和更好的方法:D

I am currently in a collage second level programing course... We are working on operator overloading... to do this we are to rebuild the vector class...
I was building the class and found that most of it is based on the [] operator. When I was trying to implement the + operator I run into a weird error that my professor has not seen before (apparently since the class switched IDE's from MinGW to VS express...) (I am using Visual Studio Express 2008 C++ edition...)

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

Errors:

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

binary '[' : no operator found which
takes a left-hand operand of type
'const Vector' (or there is no
acceptable conversion)

return newone;

error C2106: '=' : left
operand must be l-value


As stated above, I am a student going into Computer Science as my selected major I would appreciate tips, pointers, and better ways to do stuff :D

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

囍笑 2024-09-03 08:06:13

this:

int operator[ ](int);

是一个非常量成员函数。这意味着不能在 const Vector 上调用它。

通常,下标运算符的实现方式是返回一个引用(如果您返回一个值,就像您所做的那样,则不能将其用作左值,例如您不能执行 newone[j] = temp_2_int ; 就像您在代码中一样):

int& operator[](int);

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

const int& operator[](int) const;

既然您要求“提示、指针和更好的方法做一些事情:”

  • 你不能命名你的包含守卫_VECTOR_H。以下划线开头,后跟大写字母的名称保留用于实现。 很多关于下划线的规则。
  • 您不应该在标头中使用using namespace std
  • 您的 operator+ 应该采用 const Vector& 因为它不会修改其参数。
  • 您的 at 应该返回一个 int 并且应该匹配 C++ 标准库容器的语义(即,如果 i 超出,它应该抛出异常您需要使用 (*this)[i] 来调用重载的 operator[]
  • 您需要了解 * 的内容 。在一些地方,您混淆了指针和它们指向的对象,
  • 请注意混淆 === (例如,在 if (comp. 编译器将对此发出警告。
  • = 0))。如果您保证 data 永远不会出现,那么 无效的。

This:

int operator[ ](int);

is a non-const member function. It means that it cannot be called on a const Vector.

Usually, the subscript operator is implemented such that it returns a reference (if you return a value, like you are doing, you can't use it as an lvalue, e.g. you can't do newone[j] = temp_2_int; like you have in your code):

int& operator[](int);

In order to be able to call it on a const object, you should also provide a const version of the member function:

const int& operator[](int) const;

Since you ask for "tips, pointers, and better ways to do stuff:"

  • You cannot name your include guard _VECTOR_H. Names beginning with an underscore followed by a capital letter are reserved for the implementation. There are a lot of rules about underscores.
  • You should never use using namespace std in a header.
  • Your operator+ should take a const Vector& since it is not going to modify its argument.
  • Your at should return an int and should match the semantics of the C++ standard library containers (i.e., it should throw an exception if i is out of bounds. You need to use (*this)[i] to call your overloaded operator[].
  • You need to learn what the * operator does. In several places you've confused pointers and the objects to which they point.
  • Watch out for confusing = with == (e.g. in if (comp = 0)). The compiler will warn you about this. Don't ignore warnings.
  • Your logic will be much simpler if you guarantee that data is never NULL.
毁梦 2024-09-03 08:06:13

无法将其纳入对尼尔答案的评论中,所以我必须在这里详细说明。

关于您的 expand() 函数。看起来这个函数的工作是通过 n 个元素扩展具有 comp 元素的内部存储,同时保持 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 intnewdata 的开头返回的位置?! ),而且几乎可以肯定的是,如果给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,并且 *data 是一个 int,而不是指针。

这个函数应该做什么:

  • 创建一个由 comp + n 元素组成的新数组
  • ,将 size 元素从旧数组复制到新数组,
  • 删除旧数组array
  • 设置data 指向新数组

祝你好运。

Can't fit this into a comment on Neil's answer, so I'm gonna have to go into more detail here.

Regarding your expand() function. It looks like this function's job is to expand the internal storage, which has comp elements, by n elements, while maintaining the size of the Vector. So let's walk through what you have.

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

Okay, you just created a new array that is twice as big as the old one. Error: Why doesn't the new size have anything to do with n?

    if (*data != NULL) {

Error: *data is the first int element in your array. It's not a pointer. Why is it being compared to NULL?

Concept Error: Even if you said if (data != NULL), which could be a test to see if there is an array at all, at what point in time is data ever set to NULL? new [] doesn't return NULL if it's out of memory; it throws an exception.

        for (int i = 0; i <= (comp); i++) {
            newdata[i] = data[i];
        }

Warning: You're copying the whole array, but only the first size elements are valid. The loop could just run up to size and you'd be fine.

        newdata -= comp;

Error: Bad pointer math. newdata is set to a pointer to who knows where (comp ints back from the start of newdata?!), and almost certainly a pointer that will corrupt memory if given to delete [].

        comp += n;

This is fine, for what it is.

        data = newdata;
        delete newdata;
    }

Error: You stored a pointer and then immediately deleted its memory, making it an invalid pointer.

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

Error: This should be in your constructor, not here. Again, nothing ever sets data to NULL, and *data is an int, not a pointer.

What this function should do:

  • create a new array of comp + n elements
  • copy size elements from the old array to the new one
  • delete the old array
  • set data to point to the new array

Good luck.

柳絮泡泡 2024-09-03 08:06:13

除了其他人已经写过的关于您的 operator[]() 的内容之外:

您的 operator+() 采用每个非 const 引用的右侧——就好像它会试图改变它一样。然而,对于 A+B,每个人都希望 B 保持不变。

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

然后,IME 将 operator+() 基于 operator+=() 总是好的。 operator+=() 不会平等地对待其操作数(它会更改其左边的操作数),因此最好将其作为成员函数来完成。完成此操作后,在其之上实现 operator+() 就是小菜一碟了。

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

Besides of what others already wrote about your operator[]():

Your operator+() takes the right-hand side per non-const reference - as if it would attempt to change it. However, with A+B everyone would expect B to remain unchanged.

Further, I would implement all binary operators treating their operands equally (i.e., not changing either of them) as non-member functions. As member functions the left-hand side (this) could be treated differently. (For example, it could be subjected to overwritten versions in derived classes.)

Then, IME it's always good to base operator+() on operator+=(). operator+=() does not treat its operands equally (it changes its left one), so it's best done as a member function. Once this is done, implementing operator+() on top of it is a piece of cake.

Finally, operator+() should never, never ever return a reference to an object. When you say A+B you expect this to return a new object, not to change some existing object and return a reference to that.

淡笑忘祈一世凡恋 2024-09-03 08:06:13

您的代码中有太多错误,以至于很难知道从哪里开始。其一:

 delete [] data;
 *data = *newdata;

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

并且:(

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

我认为)这是一个整数向量。为什么这会返回一个字符串?对此应用 [] 运算符不会调用您的运算符 [] 重载 - 它将其视为数组,但事实并非如此。

There are so many errors in your code that it is hard to know where to start. Here's one:

 delete [] data;
 *data = *newdata;

You delete a pointer and then immediately dereference it.

And:

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

This is (I think) a vector of ints. why is this returning a string? And applying the [] operator to this does not call your operator[] overload - it treats this as an array, which it isn't.

鹤仙姿 2024-09-03 08:06:13

您需要提供两个版本的运算符[]。对于访问:

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

对于写入元素:

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

在上述两个例子中,将 T 替换为元素的类型。出现此问题的原因是,只有标记为“const”的函数才能在声明为“const”的对象上调用。将所有非变异函数标记为“const”绝对是您应该做的事情,称为“const 正确性”。由于返回对元素的引用(写入所必需的)允许底层对象发生变化,因此该版本的函数不能设为“const”。因此,需要一个只读的“const”重载。

您可能还有兴趣阅读:

You need to provide two versions of your operator[]. For accessing:

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

For writing to the element:

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

In both of the above, replace T with the type of the elements. The reason you have this problem is that only functions that are marked "const" may be invoked on an object declared to be "const". Marking all non-mutating functions as "const" is definitely something you should do and is called "const-correctness". Since returning a reference to an element (necessary for writing) allows the underlying object to be mutated, that version of the function cannot be made "const". Therefore, a read-only "const" overload is needed.

You may also be interested in reading:

人疚 2024-09-03 08:06:13
int Vector::operator[] (int place) { return (data[place]); }

这样

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

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

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

This should be

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

so that you will be able to do the [] operation on const vectors. The const after the function declaration means that the class instance (this) is treated as const Vector, meaning you won't be able to modify normal attributes. Or in other words: A method that only has read access to attributes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文