Sign in to follow this  

STL Vectors, and classes

This topic is 4544 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've just run into this problem with my Map Editor. It uses my own format called .ohm. I am trying to add support for loading models and placing them in the world, but i have a problem with using a certain class in my vector. NOTE: This source is not in one file, it is a collection of relevant code.
struct OHMHEADER
{
       char MapName[100];
       float YScale;
       char Texture1[80];
       char Texture2[80];
       char Texture3[80];
       char Texture4[80];
       char WaterTexture[80];
       float WaterLevel;
       int Step;
       std::vector<CObjModel> Models;
       BYTE *data;
       
       //Object stuff to be added...
};

//.............

class CObjModel
{
      public:
      int numVerts, numUV, numNormals, numFaces;
      bool Triangles;
      std::vector <CVector3> Verts;
      std::vector <CVector3> Normals;
      std::vector <CVector3> UVs;
      std::vector <CIndex3> Verticies;
      
      char * FileName;
      
      CObjModel();
      bool Load(char* strname);
      void Draw();
};

//.............

case IDD_ADD:
        {
             char FileName[80];
             CObjModel tempModel;
             GetDlgItemText(hWnd,IDC_ADD, FileName, 80);
             if(!tempModel.Load(FileName))
                  break;
             ohm.Models.push_back(tempModel);
             SendMessage(GetDlgItem (hWnd, IDC_COMBO),CB_ADDSTRING,0,(long)FileName);
             break;
        }


//..............

int DrawGLScene(GLvoid)								// Here's Where We Do All The Drawing
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);			// Clear The Screen And The Depth Buffer
	glLoadIdentity();	
    
	if(keys[VK_LEFT])
	rY-=1;
	if(keys[VK_RIGHT])
	rY+=1;
	if(keys[VK_UP])
	rX-=1;
	if(keys[VK_DOWN])
	rX+=1;
	if(keys[VK_ADD])
	zoom+=0.1;
	if(keys[VK_SUBTRACT])
	zoom-=0.1;
	glTranslatef(0,0,zoom);
	glRotatef(rX,1,0,0);
	glRotatef(rY,0,1,0);
	glScalef(0.015,0.015,0.015);	
	if(DataLoaded)
	{
	    DrawHeightMap(&ohm,gSolid);
	    DrawSea(&ohm);
	    
        level4.Bind();
        //Pipe.Draw();
        for(int I=0;I<ohm.Models.size();I++)
        {
           ohm.Models[I].Draw();
        }
        
    } 

ohm is a header structure for the model format, it contains a vector called Models, which holds a set of models that the user has entered previously. I have checked that it loads them into this vector, and it seems to have loaded them in. But when i try and access the Draw() function in one of the Models in the Models vector, it simply gives me a M$ error report window. I am not really sure what is wrong, the model loader works fine on its own, but it seems it does not like being called from a vector.

Share this post


Link to post
Share on other sites
What both of you probably need is to create proper copy constructor and op= for your classes I can see a few bald pointers hanging around and in this case that makes me suspect that you simply free your resources in the destructor but don't clone them properly when copying leading to both double deletions and access failiures when you try to read memory that you no longer own.

For strings I advice you to use std::string instead of char* since it will solve that and a slew of ofter problems without you needing to think about it again. For byte data why not consider std::vector<BYTE> as it does automatic memory handling also for you.

Hope that was of some assistance.

Share this post


Link to post
Share on other sites
Quote:
Original post by DigitalDelusion
What both of you probably need is to create proper copy constructor and op= for your classes I can see a few bald pointers hanging around and in this case that makes me suspect that you simply free your resources in the destructor but don't clone them properly when copying leading to both double deletions and access failiures when you try to read memory that you no longer own.

For strings I advice you to use std::string instead of char* since it will solve that and a slew of ofter problems without you needing to think about it again. For byte data why not consider std::vector<BYTE> as it does automatic memory handling also for you.

Hope that was of some assistance.


I have barely used any pointers in that. However, do i need to delete a char* pointer at the end of the program?

I use no constructors or destructors as there was no use for them IMO.

As for this copying stuff, i dont seem to have caught your drift.

Share this post


Link to post
Share on other sites
Which class is the problem?

Does that class have pointers in them?

If so then you should have destructors to delete the data from the heap.

Are they base classes. If so then you need virtual destructors.

If you are allocating heap memory then you should really have copy constructors..you should also have assignment constructors as well. The rule of 3 (or something like that) it's called.

Are you "slicing" one of the objects? Assigning a derived class to a base class.

To be honest it's a little difficult without seeing the error memssage and the other classes?

Share this post


Link to post
Share on other sites
Quote:
Original post by Kris2456
out of interest, is it possible to call functions from a class in a vector?


You mean like:

#include <iostream> //for cout
#include <vector> //for vector
#include <algorithm> //for for_each
#include <functional> //for mem_fun_ref


class foo {
public:
int i;
foo( int i ) : i( i ) {}
foo( const foo & other ) : i( other.i ) {}

void saymynumber( void ) {
std::cout << "My number is " << i << std::endl;
}
};

std::vector< foo > foos;
foos.push_back( foo( 5 ) );
foos.push_back( foo( 3 ) );
foos.push_back( foo( 4 ) );

//calls foo.saymynumber() where foo is the 3rd foo in the vector :
foos[2].saymynumber();

//calls foo.saymynumber() where foo is the foo pointed to by the iterator i (in this case the 2nd foo in the vector)
std::vector< foo >::iterator i = foos.begin(); ++i;
i->saymynumber();

//calls foo.saymynumber for foo = *[ foos.begin() .. foos.end() ) - that is, once on every foo in the vector :
std::for_each( foos.begin() , foos.end() , std::mem_fun_ref( &foo::saymynumber ) );








In a word? Yes :-).

EDIT: I need to learn to type and generally use my brain.

Share this post


Link to post
Share on other sites
Well when i ran teh debugger (and btw it didnt give me any segmentation faults) this is what it did.

I would get to this line:

ohm.Models[I].Draw();


And i would click "step into", to see what went on in that function. The problem is, is that it went into the .h file for std::vector, went through some code, and went back. I really want to see wtf is going on in Draw(). Is there any way to hack it or something?

Share this post


Link to post
Share on other sites
Quote:
Original post by Kris2456
Well when i ran teh debugger (and btw it didnt give me any segmentation faults) this is what it did.

I would get to this line:

ohm.Models[I].Draw();


And i would click "step into", to see what went on in that function. The problem is, is that it went into the .h file for std::vector, went through some code, and went back. I really want to see wtf is going on in Draw(). Is there any way to hack it or something?


When you first step into that line, it should put you within std::vector::operator[], where it's looking up the object that you're then going to call draw on. Clicking step out will bring you back to that line, where operator[] has returned with a reference to the model, but before calling Draw(). Hitting step in once more, it should enter the Draw() function.

Basically, it works a lot like if you typed:
void a( int ) {}
int b( int ) {}
int c( void ) {}

int main( void ) {
a( b( c() ) ); //breaking on this line
}

When you first hit "step in", it'll enter c(). Once you reach the end of that function (either by stepping through, or "step out") you return to that line, with c completed but b and a not. Hitting step in again will put you into b(). Again, once you step through/out, you return to the original line. Stepping in will put you in a(). Stepping through/out will finish that line.

Assuming ohm.Models is a std::vector< Model >, that line ends up looking a lot like:

Model::Draw( /*this = */ vector::operator[]( /*this = */ ohm.Models , I ) )

I've butchered the code some, the above isn't valid C++ (you can't translate foo.bar() into bar( foo ), although conceptually that's what's happening - also, the entire function name is std::vector< Model >::operator[]).

HTH

[Edited by - MaulingMonkey on July 2, 2005 2:48:42 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Kris2456
OMG! I found it!

It turns out i had forgotten to fclose my file pointer at the end of the model loading. That screwed everything up.

Thanks for the help guys!

kthxpie.


If you use modern C++ io (with (i|o|io)stream objects and the <iostream> header), this problem will disappear (unless you want to use the same file twice in the same scope), because the stream object will close() itself in the destructor. :)

Share this post


Link to post
Share on other sites

This topic is 4544 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this