<小时/> 问题:当我尝试按索引分配IntArray对象时,我收到以下错误:
&#34;表达式不可分配。&#34;
错误由iadrv.cpp中的以下代码行生成:
IntArray a(10);
for(int i = a.low(); i <= a.high(); i++)
a[i] = i * 10;
我能够将整个IntArray对象分配给另一个,如a = b;
,但是当一个特定的索引被引用到&#34时,表达式是不可分配的&#34;发生错误。
编辑:我从大多数功能中移除了const
声明,而我没有得到&#34;表达式不可分配&#34;错误了。但是,setName现在给出错误:
&#34; ISO C ++ 11不允许从字符串文字转换为&#39; char *&#39;&#34;
此错误是由iadrv.cpp中的以下代码引起的:
a.setName("a");
<小时/> 程序说明:
我编写了一个IntArray类(在C ++中),其中重载了以下运算符:
该计划还包括以下功能:
驱动程序(iadrv.cpp,iadrv.h)将对IntArray类(IntArray.cpp,IntArray.h)运行测试,以确定是否所有运算符都已正确重载。
注意:对于每个阵列测试数据,驱动程序将简单地乘以 在每个数组初始化或修改后立即将数组索引10并输出其内容。当程序遇到运行时错误时,应该通过适当的诊断模拟&#34;停止而不是实际停止程序。
<小时/> 代码:
IntArray.h
// IntArray.h
#ifndef __IntArray__IntArray__
#define __IntArray__IntArray__
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
class IntArray {
private:
int a, b;
int size;
int * num;
char * name;
public:
IntArray(int start, int finish);
IntArray(int finish = 10);
IntArray(const IntArray &); //constructor copy
~IntArray();
int low() const;
int high() const;
char * getName() const;
//removed the const declaration from functions below
int & operator [] (int); //made to return int&
friend ostream & operator << (ostream &, IntArray &);
void setName(char *);
int length() const;
const IntArray & operator = (IntArray &);
const IntArray & operator + (IntArray &);
bool operator += (IntArray &);
};
#endif /* defined(__IntArray__IntArray__) */
IntArray.cpp
// IntArray.cpp
#include "IntArray.h"
#include <iostream>
#include <fstream>
using namespace std;
extern ofstream csis;
IntArray::IntArray(int start, int finish) {
if (start > finish) {
cout << "Simulating a halt.";
a = finish;
b = start;
}
else {
a = start;
b = finish;
}
size = b-a;
num = new int[size];
name = new char[1];
for (int i = 0; i < size; i++) {
num[i] = 0;
}
}
IntArray::IntArray(int finish) {
size = finish;
a = 0;
b = finish - 1;
num = new int[size];
name = new char[1];
for (int i = 0; i < size; i++) {
num[i] = 0;
}
}
IntArray::IntArray (const IntArray & right): size(right.size) {
num = new int[size];
name = new char[1];
for (int i = 0; i < size; i++) {
num[i] = right.num[i];
}
}
IntArray::~IntArray() {
delete[] num;
delete [] name;
}
int IntArray::low() const{
return a;
}
int IntArray::high() const{
return b;
}
char * IntArray::getName() const{
return name;
}
void IntArray::setName(char * n) {
name = n;
}
//removed const declarations
//made to return int&
int & IntArray::operator [] (int subscript) const{
if (subscript < a || subscript > b) {
cout << "subscript: " << subscript << endl;
cout << "Out of bound error. Simulating a halt." << endl;
return num[a];
}
return num[subscript-a];
}
int IntArray::length() const{
//b-a = size
return (b-a);
}
//removed const declarations
ostream & operator << (ostream & output, IntArray & array) {
for (int i = array.low(); i <= array.high(); i++) {
output << array.name << "[" << i << "] = " << array[i] << endl;
}
return output;
}
//removed const declarations
IntArray & IntArray::operator = (IntArray & right) {
if (length() == right.length()) {
for (int i = 0; i <= length(); i++) {
num[i] = right[right.low()+i];
}
return * this;
}
else {
delete [] num; //reclaim space
delete [] name;
size = right.length();
num = new int [size]; //space created
cout << "Different sized arrays. Simulating a hault" << endl;
}
return * this;
}
//removed const declarations
IntArray & IntArray::operator + (IntArray & right) {
int * ptr;
ptr = new int [right.length()];
if (length() == right.length()) {
for (int i = 0; i < length(); i++) {
ptr[i] = num[i] + right[right.low()+i];
}
}
return * this;
}
//removed const declarations
bool IntArray::operator += (IntArray & right) {
if (length() == right.length()) {
for (int i = 0; i <= right.length(); i++) {
num[i] += right[right.low()+i];
}
return true;
}
cout << "Could not add the sum of the arrays into first array. Simulating a halt." << endl;
return false;
}
iadrv.h
// iadrv.h
#ifndef p6_iadrv_h
#define p6_iadrv_h
#include "intarray.h"
int main();
void test1();
void wait();
#endif
iadrv.cpp
// iadrv.cpp
#include <iostream>
#include <iomanip>
#include <fstream>
#include <stdlib.h>
#include "iadrv.h"
using namespace std;
ofstream csis;
int main() {
csis.open("csis.dat");
test1();
csis.close();
}
void test1() {
system("clear");
cout << "1. Array declared with single integer: IntArray a(10);" << endl << endl;
csis << "1. Array declared with single integer: IntArray a(10);" << endl << endl;
IntArray a(10);
for(int i = a.low(); i <= a.high(); i++)
a[i] = i * 10;
a.setName("a");
cout << a << endl;
csis << a << endl;
wait();
}
免责声明:此计划是作为学校作业编写的,已经被录入评分。这是我的第一个c ++程序,所以我想了解我的错误。非常感谢您的帮助。
答案 0 :(得分:1)
您已经定义了这样的运算符[]:
const int operator [] (int) const;
第二个“const”意味着在该方法中你无法修改你的对象。
因此它只适用于获取值,但不适用于设置它们。
尝试删除它,它应该可以工作。
编辑:AS指出Bryan Chen,你还需要返回一个引用和非const,如下所示:int& operator [] (int subscript)
现在,深入研究一下你的代码,这还不够,因为你有这个方法:
ostream & operator << (ostream & output, const IntArray & array) {
for (int i = array.low(); i <= array.high(); i++) {
output << array.name << "[" << i << "] = " << array[i] << endl;
}
return output;
}
看看operator []需要处理非const IntArray,但是在那个方法中你的变量“array”是const,所以你需要重写一些代码。
另外,查看其余运算符的相同问题,请记住:只有在不打算从该方法内部修改对象时才创建方法'const',并创建参数'const'仅当您不打算修改该参数时。
答案 1 :(得分:0)
您现有的运算符不允许更改值,因为它返回值int
并且因为运算符被声明为const。您不能将值分配给一个对象(包括引用,因为引用只是对象的另一个名称)。
要完成此任务,您需要使用另一个非常量运算符来补充现有运算符,该非常量运算符将返回对(非常量)int
的引用:
int & operator[](int index);
由于此运算符将返回引用,因此您可以使用您希望使用的熟悉的a[b] = c
语法直接指定返回值。
您不会需要来更改现有的运算符,但我强烈建议您将返回类型从const int
更改为int
- 无论如何,您都要返回值,所以你要交回副本。这对于const来说是没有意义的,这可能会阻止编译器在比int
更复杂的数据类型的情况下删除副本。 (它在这里确实没什么区别,但是我会避免养成按值和 const返回的习惯,因为 - 假设存在复制构造函数 - const通过简单地再次复制值,无论如何都可以删除限定符。返回const副本通常没有任何好处,但有几个缺点。)
答案 2 :(得分:0)
既然你也要求指出你的错误,我想评论你应该/可以做的两件事,以使代码更简单:
首先,赋值运算符可以这样写:
IntArray& operator=(IntArray rhs)
{
std::swap(rhs.a, a);
std::swap(rhs.b, b);
std::swap(rhs.size, size);
std::swap(rhs.num, num);
std::swap(rhs.name, name);
return *this;
}
这是有效的,因为你已经为IntArray
定义了一个复制构造函数和析构函数,并且它们有望正常工作。所有赋值运算符都在创建一个临时对象,并使用当前对象的内部交换其内部。然后临时模具带有旧数据&#34;,而新数据安全地存在于当前对象中。这称为copy/swap
成语。
另请注意,返回的引用为non-const
。
如果传递const引用而不是对象,则赋值运算符负责初始复制。
IntArray& operator=(const IntArray& orig)
{
IntArray rhs(orig);
std::swap(rhs.a, a);
std::swap(rhs.b, b);
std::swap(rhs.size, size);
std::swap(rhs.num, num);
std::swap(rhs.name, name);
return *this;
}
前一版本可能更快,因为允许编译器优化传递值的副本。但是,传递const引用的第二种形式是通常所做的 - 请注意,在继续之前需要在函数内部创建临时对象。
其次,您的operator +
可以使用operator +=
:
IntArray operator+(const IntArray& rhs)
{
IntArray temp(*this);
return temp += rhs;
}
我们所做的就是创建一个等于当前对象的临时对象。然后我们使用+=
添加rhs
并返回结果。很好,很简单。请注意,operator +
返回一个新的IntArray
对象,而不是const
IntArray。此外,operator +=
应返回对当前对象的引用,而不是bool
。
为了利用这一点,您的operator +=
应该被重写:
IntArray& operator+=(const IntArray& rhs)
{
//..your current code goes here:
//...
return *this;
}
此外,您的operator +=
不应该是&#34;错误输出&#34;像那样。您需要尝试添加两个可能不同大小的IntArray
来使类更健壮。如果确实存在错误抛出异常。不要返回bool - 完全删除该函数中的return true;
和return false;
。始终返回*this
。