我目前正处于拼贴二级编程课程......我们正在研究运算符重载...要做到这一点,我们要重建矢量类...
我正在构建课程,发现其中大部分是基于[] operator
。当我试图实现+ operator
时,我遇到了一个奇怪的错误,我的教授之前没有见过(显然是因为班级将IDE从MinGW切换到VS表达...)(我使用的是Visual Studio Express 2008 C ++版...)
#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
#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
答案 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
设置为*data
,int
是comp + n
,而不是指针。
这个函数应该做什么:
size
元素数组data
元素复制到新数组答案 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
,这意味着您将无法修改常规属性。或者换句话说:一种只具有对属性的读访问权的方法。