我正在尝试完成一项家庭作业,以创建一个Shape类层次结构。在main()中,我试图填充一个指向Shape对象的指针数组。然后,在填充之后,我需要遍历该数组并在每个对象指针上调用print()(这里称为" SendToString")函数。
运行时,在我输入一些形状然后输入“完成”后,它会在运行时在第二个for循环中崩溃。它似乎无法遍历shape_array?
在getShape()中,如果用户键入' done'在控制台中,返回NULL指针。当从getShape()返回NULL指针时,main()中的循环应该退出并停止填充数组。
我的代码出了什么问题?我梳理了几个小时,看不出问题。感谢。
#include "stdafx.h"
#include <iostream>
#include "Shape.h"
#include <string>
using namespace std;
Shape* getShape();
int main()
{
int i; //fill the shape array.
int j; //loop through the shape array.
string output;
Shape* shape_array[15]; //array of base Shape pointers
Shape *shape_ptr;
int nElements = sizeof(shape_array) / sizeof(shape_array[0]);
cout << "Enter a list of shapes - 'done' to end" << endl;
//fill the array of shape object pointers
for (i =0; i <= nElements; i++) { //loop through the defined array of 15 elements
shape_ptr = getShape(); //return a shape ptr or NULL ptr
if (shape_ptr== NULL)
{
break; //stop filling the array (stop calling getShape)
}
else
{
shape_array[i]= shape_ptr; //add the shape pointer
}
} //end for
cout << "The list of shapes entered..." << endl;
for (j = 0; j < nElements; j++) {
output = shape_array[j]->SendToString();
cout << output << endl;
}
return 0;
} //end main
这是输出:
Enter a list of shapes - 'done' to end
Enter the shape's color (or 'done')...
green
Enter shape type...
circle
Enter the radius...
5.0
Enter the shape's color (or 'done')...
red
Enter shape type...
circle
Enter the radius...
4.0
Enter the shape's color (or 'done')...
done
User entered done!
The list of shapes entered...
green circle with a radius of 5 and area of 78
它无法打印第二个对象并在那里崩溃。
答案 0 :(得分:3)
就像juanchopanza在他的评论中所说,你正在访问阵列越界。
for (j = 0; j <= nElements; j++) {
应该是:
for (j = 0; j < nElements; j++) {
如果我定义一个大小为2的数组,如:
int i[2];
然后我可以使用i [0]访问第一个元素,使用i [1]访问第二个元素。这是访问的所有2个元素,我无法访问i [2]。 C / C ++数组中可接受的索引范围始终为0到(nElements-1)。
看到这个: http://www.cplusplus.com/doc/tutorial/arrays/
另请注意,在最后一个循环中,如果没有为数组中的所有15个点输入形状,则会遍历整个数组。这些导致您尝试访问垃圾指针指向的内存,因此可能未映射。这很可能导致崩溃。
答案 1 :(得分:2)
除了第一个循环中明显的越界访问外,您还要处理整个数组,就像它的所有元素指向有效对象一样:
for (j = 0; j < nElements; j++) {
output = shape_array[j]->SendToString();
但是不能保证它们是,因为你只在NULL
返回第一个getShape()
之前设置元素,否则你会因为你的奇怪循环技术而无法设置元素,你在那里做某事像这样:
for (i =0; i < nElements; i++)
{
shape_array[i]= something_good;
i++; // LOOK! Index increased one extra time per loop!!!
}
在第一个循环中,您只设置数组中的每个第二个元素,但是您取消引用所有这些元素。您正在取消引用无效指针。如果您要编写此类代码,则应学会使用调试器。
答案 2 :(得分:1)
数组索引的所有有效范围中的第一个是[0, nElements - 1]
其次,两个循环都写得不正确并包含错误。例如,在第一个循环变量中,i增加两次。
正确的代码可以采用以下方式
#include "stdafx.h"
#include <iostream>
#include <string>
#include "Shape.h"
Shape *getShape(); // Why this function is declared here but not is defined in the module?!
int main()
{
const int N = 15;
Shape* shape_array[N]; //array of base Shape pointers
std::cout << "Enter a list of shapes - 'done' to end" << std::endl;
//fill the array of shape object pointers
Shape *shape_ptr;
int nElements = 0;
for ( ; nElements < N && ( shape_ptr = getShape() ); nElements++ )
{
//loop through the defined array of 15 elements
shape_array[nElements] = shape_ptr; //add the shape pointer
} //end for
std::cout << "The list of shapes entered..." << std::endl;
for ( int i = 0; i < nElements; i++ )
{
std::string output = shape_array[i]->SendToString();
std::cout << output << std::endl;
}
return 0;
}