Extremely basic question RE: arrays in c++

Started by
9 comments, last by jjavahe 16 years, 2 months ago
I have an enemies class, here...
class Enemy {
	public:
	
    float currentX, currentY;

	Enemy() {
		currentX = 0.0;
		currentY = 0.0;
    }   
                 
	Enemy(float xPos, float yPos) {
		currentX = xPos;
		currentY = yPos;
    }   

	void setCurrentX(float f){
		currentX = f;
	}

	void setCurrentY(float f){
		currentY = f;
	}

	float getCurrentX(){
		return currentX;
	}

	float getCurrentY(){
		return currentY;
	}

	void draw(){
			glPushMatrix();

				//Push turret
				glTranslatef(currentX,currentY,0);
				glScalef(1, 1, 1);
				glmDraw(model_tankBase,GLM_TEXTURE);

			glPopMatrix();
	}

	void move(){
		currentX ++;
	}


};
Now in my main.cpp, I want to create an array of type Enemy, length 5. So I have done this...
	Enemy *enemies[5];
	enemies[0] = new Enemy();
	enemies[0]->setCurrentX(90.0);
	enemies[0]->setCurrentY(50.0);

//STATES
void level_menu(){


	enemies[0]->draw();
	enemies[0]->move();
}
However this does not seem to work! Its telling me "cannot allocate an array of constant size 0" and "missing type specifier - int assumed. Note: C++ does not support default-int" and "cannot convert from 'Enemy *' to 'int []'" Its definately defining my array, but I dont see how I can access each position and call a method on it... So basically I just want to be able to define an array of Enemies and modify their positions via their helper methods... But I cant get past defining them properly =( I am migrating from java and some of this seems unintuitive, sorry!
Advertisement
Quote:Now in my main.cpp, I want to create an array of type Enemy, length 5. So I have done this...

Enemy *enemies[5];

enemies[0] = new Enemy();

enemies[0]->setCurrentX(90.0);

enemies[0]->setCurrentY(50.0);


Unlike Java, you don't need to use new to create objects in C++. If you don't want to deal with references (which is what you're used to in Java), you can create an array of 5 Enemies rather than 5 Enemy references. You would do this:

Enemy enemies[5];enemies[0].setCurrentX(90.0);enemies[0].setCurrentY(50.0);


This might prevent some errors in the future if you used real Enemies rather than references.
Can you look at my Enemy class and tell me if everything is alright in there? Because I did exactly as you said and I get these errors:

: error C2466: cannot allocate an array of constant size 01>c:\users\joshua javaheri\documents\school\cap4730 graphics\assignment 1\assignment 1\main.cpp(112) : error C2143: syntax error : missing ';' before '.'1>c:\users\joshua javaheri\documents\school\cap4730 graphics\assignment 1\assignment 1\main.cpp(112) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int1>c:\users\joshua javaheri\documents\school\cap4730 graphics\assignment 1\assignment 1\main.cpp(112) : error C2371: 'enemies' : redefinition; different basic types1>        c:\users\joshua javaheri\documents\school\cap4730 graphics\assignment 1\assignment 1\main.cpp(110) : see declaration of 'enemies'1>c:\users\joshua javaheri\documents\school\cap4730 graphics\assignment 1\assignment 1\main.cpp(113) : error C2466: cannot allocate an array of constant size 01>c:\users\joshua javaheri\documents\school\cap4730 graphics\assignment 1\assignment 1\main.cpp(113) : error C2143: syntax error : missing ';' before '.'1>c:\users\joshua javaheri\documents\school\cap4730 graphics\assignment 1\assignment 1\main.cpp(113) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int1>c:\users\joshua javaheri\documents\school\cap4730 graphics\assignment 1\assignment 1\main.cpp(113) : error C2371: 'enemies' : redefinition; different basic types1>        c:\users\joshua javaheri\documents\school\cap4730 graphics\assignment 1\assignment 1\main.cpp(110) : see declaration of 'enemies'
Quote:Original post by jjavahe
*** errors ***
Can you post your revised code in its entirety?
The enemy cpp is as I posted above, here is my main

Thanks!

#include "glut.h"#include "glm.h"GLMmodel *model_tankBase;GLMmodel *model_tankTurret;float baseScaleX = 8.0, baseScaleY = 8.0, baseScaleZ = 8.0;float baseTranslateX = 0.0, baseTranslateY = 0.0, baseTranslateZ = 0.0;float baseRotateZ = 0.0;float turretRotateZ = 0.0;int state = 2;#include <cmath>#include <stdlib.h>#include <stdarg.h>#include <iostream>#include <memory.h>#include <time.h>#include <fstream>#include "Enemy.cpp"#define PI 3.141592654using namespace std;// Default Image dimensionsint imageWidth = 640;int imageHeight = 480;// the circle object, initialized in setupGL()GLUquadricObj* circle = NULL;  //OpenGL Callsvoid setupGL();void CheckGLError();//Callbacksvoid Display();void Idle();void Reshape(int w, int h);void Keyboard (unsigned char key, int , int );void SpecialKeyboard(int key, int x, int y);void MouseButton(int button, int state, int x, int y);void MouseMotion(int x, int y);//fontGLvoid *font_style = GLUT_BITMAP_HELVETICA_12;// a cleanup functionvoid quit(int i = 0);void main(int argc, char **argv){	// INITIALIZE THE GLUT WINDOW	glutInit(&argc, argv);  	glutInitWindowSize(imageWidth, imageHeight);	glutInitDisplayString("rgb double");	glutInitWindowPosition(0, 0);	glutCreateWindow("Project #1");	//SETUP GLUT CALLBACKS	cout << "Setting up callbacks... ";	glutDisplayFunc(Display);	glutKeyboardFunc(Keyboard);	glutSpecialFunc(SpecialKeyboard);	glutMouseFunc(MouseButton);	glutMotionFunc(MouseMotion);	glutReshapeFunc(Reshape);	glutIdleFunc(Idle);	cout << "[completed]\n";	glEnable(GL_DEPTH_TEST);	//SETUP MISC GL	setupGL();	CheckGLError();	model_tankBase = glmReadOBJ("data/tankBase.obj");	model_tankTurret = glmReadOBJ("data/tankTurret.obj");	glutMainLoop();}// This function checks the state of openGL and prints // an error if an error has occurredvoid CheckGLError(){  	GLenum error;  	error = glGetError();  	if (error!=GL_NO_ERROR)  	{		cout << "OpenGL reports an error: "<< gluErrorString(error) << endl;		quit(1);  	}}//drawstr method from Nate Robbins tutorials, 1997void drawstr(GLuint x, GLuint y, char* format, ...){	va_list args;    char buffer[255], *s;        va_start(args, format);    vsprintf(buffer, format, args);    va_end(args);        glRasterPos2i(x, y);    for (s = buffer; *s; s++)        glutBitmapCharacter(font_style, *s);}	Enemy enemies[5];	//enemies[0] = new Enemy();	enemies[0].setCurrentX(90.0);	enemies[0].setCurrentY(50.0);//STATESvoid level_menu(){	//enemies[1]->draw();	//enemies[1]->move();}void level_01(){	glPushMatrix();		//Push base		glTranslatef(baseTranslateX,baseTranslateY,0);		glRotatef(baseRotateZ, 0, 0, 1);		glScalef(baseScaleX, baseScaleY, baseScaleZ);		glmDraw(model_tankBase,GLM_TEXTURE);			glPushMatrix();				//Push turret				glTranslatef(0,0,0);				glRotatef(turretRotateZ,0,0,1);				glScalef(1, 1, 1);				glmDraw(model_tankTurret,GLM_TEXTURE);			glPopMatrix();	glPopMatrix();}void level_credits(){}//END STATESvoid Display(){	// clear the screen	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	//Render the model	if(state == 1){		level_menu();	}	else if(state == 2){		level_01();	}	else{		level_credits();	}		//draw text	drawstr(30.0, 460, "x = ");	drawstr(50.0, 460, "%.1f", 3.0);	// swap the buffers	glutSwapBuffers();}//HELPERSfloat convertToRadians(float degree){	float radian;	radian = (PI/180)*degree;	return radian + (PI/2);						//I add PI/2 because the coordinate system is off by 90 degrees}//TRANSFORMATIONSvoid baseScaleUp(){	if(baseScaleX <= 12 && baseScaleY <= 12 && baseScaleZ <= 12){		baseScaleX++;		baseScaleY++;		baseScaleZ++;	}}void baseScaleDown(){	if(baseScaleX > 1 && baseScaleY > 1 && baseScaleZ > 1){		baseScaleX--;		baseScaleY--;		baseScaleZ--;	}}void baseTranslatePositive(){	baseTranslateX += 2*cos(convertToRadians(baseRotateZ));	baseTranslateY += 2*sin(convertToRadians(baseRotateZ));}void baseTranslateNegative(){	baseTranslateX -= 2*cos(convertToRadians(baseRotateZ));	baseTranslateY -= 2*sin(convertToRadians(baseRotateZ));}void baseRotateZPositive(){	baseRotateZ += 1;	if(baseRotateZ >= 360){		baseRotateZ = 0;	}}void baseRotateZNegative(){	baseRotateZ -= 1;	if(baseRotateZ >= 360){		baseRotateZ = 0;	}}void turretRotateZPositive(){	turretRotateZ += 3;	if(turretRotateZ >= 360){		baseRotateZ = 0;	}}void turretRotateZNegative(){	turretRotateZ -= 3;	if(turretRotateZ >= 360){		baseRotateZ = 0;	}}//END TRANSFORMATIONS// set up GL stuffvoid setupGL() {	// set the clear color	glClearColor(0.0, 0.0, 0.0, 1.0);  // background color	// initialize the circle object	circle = gluNewQuadric();	if (!circle) { 		cout << "The circle object could not be created!  Quitting..." << endl;		quit(1);	}}// This function is continuously called when events are not being received// by the window.  This is a good place to update the state of your objects // after every frame.void Idle() {	glutPostRedisplay();}// This functions handles what happens when the window is reshapedvoid Reshape(int w, int h) {	imageWidth = w;	imageHeight = h;   	glViewport(0,0,w,h);	glMatrixMode(GL_PROJECTION);   	glLoadIdentity();	gluOrtho2D(-100, 100, -100, 100);    glMatrixMode(GL_MODELVIEW);	glLoadIdentity();}void processNormalKeys(unsigned char key, int x, int y) {	if (key == 27) 		exit(0);}// a cleanup function.  call this when you want to exit.void quit(int i) {	// cleanup the circle object	if (circle)		gluDeleteQuadric(circle);	exit(i);}void SpecialKeyboard(int key, int x, int y){	switch(key){		case GLUT_KEY_UP:			baseTranslatePositive();			break;		case GLUT_KEY_DOWN:			baseTranslateNegative();			break;		case GLUT_KEY_LEFT:			baseRotateZPositive();			break;		case GLUT_KEY_RIGHT:			baseRotateZNegative();					break;	}}// keyboard handlervoid Keyboard (unsigned char key, int , int ){	switch(key)    {		// if esc or q, exit		case 27:        case 'u':			baseScaleUp();			break;		case 'i':			baseScaleDown();			break;		case 'n':			turretRotateZPositive();			break;		case 'm':			turretRotateZNegative();			break;	}}void MouseButton(int button, int state, int x, int y){	switch (button) 	{		case GLUT_LEFT_BUTTON:		    break;		case GLUT_MIDDLE_BUTTON:		    break;		case GLUT_RIGHT_BUTTON:		    break;	}}void MouseMotion(int x, int y){}
When I comment out the calls to the methods it appears to compile fine, but when I call the methods it doesnt seem to like it which means I think there is something wrong with how I am calling it or how its setup?

Enemy enemies[5];	//enemies[0] = new Enemy();	enemies[0].setCurrentX(90.0);	enemies[0].setCurrentY(50.0);//STATESvoid level_menu(){	//enemies[1]->draw();	//enemies[1]->move();}

Hi jjavahe,

I think your problem is the uncomment of

//enemies[0] = new Enemy();

--edit--
i ran your class through vs08 and it works fine when the objects are initialised locally. i get the same errors when its initialised globally

jyk is correct
--end edit--


I hope you find a solution, good luck
---Terence Burns---
It looks like you have some executable code there (e.g. 'enemies[0].setCurrentX(90.0)') that is not inside the body of a function. (Although there are cases where such code can exist outside of a function body, this isn't one of them.)
Jesus, this whole time I just had to put it in a function! Thanks.

0) Don't write that much code at once without testing anything. Especially in a compiled language.

1) Yeah, the code has to be in a function. Outside, basically all you can do is initialize globals. Otherwise, how do you expect to control when it happens? :)

2) Don't use 'set' functions to set up an object. Use a constructor. You are supposed to know about these from Java. In fact, try to avoid 'set' functions as much as possible. You are supposed to know this design principle from Java, but unfortunately there are a lot of self-titled "Java experts" going around promoting some very strange ideas. Sorry about that.

3) Don't #include your .cpp file. Use headers. More on that. C++ doesn't have a proper import model like Java. Sorry.

4)
Quote://drawstr method from Nate Robbins tutorials, 1997


...

O_o

Please, for a second, think about the computer you had in 1997, compared to the one you own now.

Yeah.

Eleven years is an eternity in the computer world. The C++ language was re-standardized in 1998, anyway. Anything written about from before then is liable to be outright wrong, simply because of its age. (Of course, older stuff is more likely to be "wrong" on average anyway, in more subtle ways, simply because of people playing catch-up, and because of computer science as a whole getting cleverer over time.)

But yeah, don't do varargs functions in C++. Just say no. In C++, we use streams to format text.

This topic is closed to new replies.

Advertisement