Skip to main content
gamedev.net
🔒 Locked

Pointers to classes

Started by Xtreme Jan 7, 2003 at 12:04 AM 47 replies 1.1k views
Original Post
Xtreme
Xtreme
hi all, I am playing around with Class declarations and creating objects with "new" and I am wondering what the difference between this 2 are: (they both seem to equally work well) Assuming you have a Class called "ABC": and in another class you have a pointer which is of type "ABC" eg. ABC *abc; So what is the difference between: abc = &ABC(); and abc = new ABC(); and they both work fine
Yes! There are kangaroos in Australia but I haven't seen them...yet
Xtreme
Xtreme
forgot to mention that im calling the default constructor of class "ABC" and is used in another class "DEF"

-Xtreme
Yes! There are kangaroos in Australia but I haven't seen them...yet
guppy
guppy
quote:
Original post by Xtreme
abc = &ABC();

and

abc = new ABC();

and they both work fine



Dont think I've ever seen the first one before...

But it seems that the first one is allocated staticly and the second dynamicly.

this means that since the second is in dynamicly allocated you need to explicitly delete it, while the first one is delete automaticly when the program exits...

[edit]
tried to correct som horible spelling
[/edit]


/Please excuse my bad spelling - My native language is binary not english
|Visit me
\Take my advice - I don''t use it...

[edited by - guppy on January 7, 2003 1:14:53 AM]
/Please excuse my bad spelling - My native language is binary not english|Visit meTake my advice - I don''t use it...
Xtreme
Xtreme
that is exactly the case, but both seem to work fine
Yes! There are kangaroos in Australia but I haven't seen them...yet
DerekSaw
DerekSaw
The first one, is quite dangerous - you point to an address return from a temporary object.

The second one seems ok enough, provided you remember to delete after you are not using it.
"after many years of singularity, i'm still searching n the event horizon" o
Qw3r7yU10p!
Qw3r7yU10p!
quote:
abc = &ABC();


this will create an ABC object, take it's address, the object will be destroyed and the address assigned to the variable abc.

quote:
they both work fine


by 'work' I assume you mean 'compile'.

You won't be able to actually use the ABC object as it no longer exists. The code doesn't do what you think it does but it is legal c++

For example:

ABC* ptr1 = 0;
{
ABC obj = ABC();
ptr1 = &first
ABC* ptr2 = &first
}

The object 'obj' will remain in scope until the end of the curly braces, after which point it will be destroyed. The pointer 'ptr1' which did point to the object will no longer be valid. The pointer 'ptr2' which also points to obj will also go out of scope and be detroyed at the curly brace so there is no problem there. The compiler will allow you to use 'ptr1' after the curly braces but not 'ptr2'. In effect you have the equivalent of ptr1. It compiles but won't work as you intend.

This is why 'new' is used: if you don't use it the object will be destroyed at the end of the scope. the containers in the standard library can take care of things like that for you so it's possible to hardly ever use 'new'. But, if you want to look after memory and objects that will exist for longer than the duration of a function, then 'new' will be used somewhere.

[edited by - petewood on January 7, 2003 10:19:35 AM]
Xtreme
Xtreme
Petewood, i can understand where your coming from but what if you have the ABC *abc pointer declared as part of your class?
And then use that pointer in one of the methods in your class.

I tried that and it runs fine, and the program does not crash.

For eg.


class DEF
{

DEF(); //default constructor
~DEF(); //default destructor

public:
void DoCalc();

private:
int s;


ABC *abc; //ABC is a class defined elsewhere provided you have the right #defines above

}


And your Default constructor DEF() is:

DEF::DEF()
{
abc = &ABC(); //call the ABC class and assign the address
}


and the DoCalc() is like this:

void DEF::DoCalc()
{
s = abc.getValue();
}


And the result works fine!

The same stuff works with abc = new ABC();

but i need to have delete abc; in the destructor
Yes! There are kangaroos in Australia but I haven't seen them...yet
ga
ga
this works fine??? do a bit more testing it shouldn''t work that fine. abc is pointing to some stack memory ( and the argument that the pointer is in the class is pointless because it would point to the same memory position if it where e.g. a global variable)
the data members get overwritten regularly by stack activities of the programs (try it!), if there are virtual functions the vtable is also overwritten so the program should crash if you call them in DEF::DoCalc().

GA
Visit our homepage: www.rarebyte.de.stGA
DerekSaw
DerekSaw
quote:
Original post by Xtreme
I tried that and it runs fine, and the program does not crash.


You are darn lucky. But lucks don''t always follow you. Pls don''t do it this way, again.
"after many years of singularity, i'm still searching n the event horizon" o
johnnie2
johnnie2
Please continue developing your program for a couple months and suddenly run into a bug that''s *impossible* to track down. Congratulations, it''s probably a pointer to obscure memory that''s decided to go bad...

RapscallionGL - arriving soon.
____________"Optimal decisions, once made, do not need to be changed." - Robert Sedgewick, Algorithms in C
Arild Fines
Arild Fines
C++ doesn''t have pointers to classes.



I''ve looked at the source, and there are pieces that are good and pieces that are not ... My experience and some of my friends'' experience is that Linux is quite unreliable. Microsoft is really unreliable but Linux is worse. -- Ken Thompson
--AnkhSVN - A Visual Studio .NET Addin for the Subversion version control system.[Project site] [IRC channel] [Blog]
Qw3r7yU10p!
Qw3r7yU10p!
Xtreme: post real code please

This won''t even compile - let alone run without crashing.

  void DEF::DoCalc()
{
s = abc.getValue();// abc is a pointer which

// needs ''->'' to access it

// not ''.''

}


As another poster said, if it works you''re lucky. Or should I say unlucky, because you''re being led to believe that it''s correct, when in fact you can see by our explanations that it''s not.

Don''t rely on a non-complaining compiler or even non-crashing code to satisfy you that your code is correct.
Xtreme
Xtreme
Ok,
I am posting the *real* code below that currently seems to run fine:

The d3ds.h header file:
Note the dtexture.h header file which has a class called Dtexture which is used below:


    

#ifndef __D3DS__
#define __D3DS__

#include <stdlib.h>
#include <stdio.h>

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include "dtexture.h"

.....

class D3ds
{

public:

D3ds(FILE *);
D3ds();
~D3ds();

OGLScene *Read3dsfile(char *);

private:

uint dgetpos();
void * getmem(int);
void dsetpos(uint);
void dread(void *, int);
void OGLFreeScene();
void ReadName(char *, uint);
void ReadObjMeshBlocks(uint);
void ReadObjectBlocks(uint);
void ReadMaterialBlocks(uint);
void ReadTriMeshBlocks(uint, char *);
void ReadFaceMat(uint, OGLObject *);
void ReadMapList(uint, OGLObject *);
void ReadFaceList(uint, OGLObject *);
void ReadVertList(uint, OGLObject *);
void ReadTraMatrix(uint, OGLObject *);
void ReadAmbient(uint, OGLMaterial *);
void ReadAmbientColor(uint, OGLMaterial *);
void ReadDiffuse(uint, OGLMaterial *);
void ReadDiffuseColor(uint, OGLMaterial *);
void ReadSpecular(uint, OGLMaterial *);
void ReadSpecularColor(uint, OGLMaterial *);
void BuildMaterials(OGLObject *);
void UploadTextures();

OGLMaterial * GetMaterial();
OGLObject * GetObject();
Dtexture *tex; //take special note of this


char emsg[100];
FILE *file, *fp;
OGLScene *Scene;
};

#endif



The dtexture.h header file with class Dtexture in case you were wondering:



#ifndef __DTEXTUREH__
#define __DTEXTUREH__

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include "ijl15.h"

#define DATA_PATH "data/" //path where the 3ds and textures will be

#define MAX_TEXTURES 300

typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;

class Dtexture {

public:
Dtexture(FILE *f) : data(0), TextureUploaded(false), file(0), fp(f), texID(0) {} //initialise variables

Dtexture() : data(0), TextureUploaded(false), file(0), fp(0), texID(0) {} //initialise variables

~Dtexture() { CleanUp(); }

uint LoadTexture(char *filename, bool createMipMaps); //returns texture ID


private:
char emsg[100];
bool TextureUploaded; //is the texture loaded into mem?

uint TexList[MAX_TEXTURES]; //texture ID

int width, height, bits; //texture attributes

int texID;
uchar *data; //texture data

ulong texSize; //texture size

ulong size;

uint UploadTexture(bool createMipMaps);
void CleanUp();
void LoadJpg(char *filename);
void LoadBmp(char *filename);
void LoadTga(char *filename);
void LoadPcx(char *filename);
ulong fileSize();
ushort getMemShort(uchar * buffer, int offset);
FILE *file, *fp; //file is used for opening pics and fp is used for debugging to a file

};

#endif



And the d3ds.cpp file which makes use of the Dexture class with *tex pointer:

Please look at the function UploadTextures() below which makes use of *tex:


#include "d3ds.h"
/*******************************************************************************************/
D3ds::D3ds(FILE *f)
{
Scene = NULL;
fp = f;
}
/*******************************************************************************************/
D3ds::D3ds()
{
Scene = NULL;
fp = NULL;
}
/*******************************************************************************************/
D3ds::~D3ds()
{
OGLFreeScene();

}
/*******************************************************************************************/



..........

void D3ds::UploadTextures()
{
OGLMaterial* mat;
uint texID;
int tcount =0, tfail =0;

if (fp) fprintf(fp, "\n%d materials loaded\n", Scene->materials);
for (int n=0; n < Scene->materials; n++)
{
mat = &Scene->matlist[n];
if (strlen(mat->filename) > 0) //is a texture map defined?

{
if (Scene->tex == NULL) //allocate memory for Dtexture class

{
Scene->tex = &Dtexture(fp);//notice how I call the constructor and initialised the object *tex*

if (Scene->tex == NULL)
throw "Cannot allocate memory for the texture class";
}
texID = Scene->tex->LoadTexture(mat->filename, 1);
if (texID == 0xFFFFFFFF) {
mat->texUploaded = false;
mat->texID = 0;
tfail++;
}
else {
mat->texUploaded = true;
mat->texID = texID;
}
tcount++;
}
}
if (fp) fprintf(fp, "%d textures loaded\n", tcount-tfail);
if (fp && (tfail > 0)) fprintf(fp, "Failed to load %d textures\n", tfail);
}



And to confirm that it compiles and links fine (and runs fine but I cant show you that it works here)



--------------------Configuration: OGLCrystal - Win32 Release--------------------
Compiling resources...
Compiling...
demo.cpp
dmath.cpp
main.cpp
winapp.cpp
bands.cpp
tubes.cpp
d3ds.cpp
dtexture.cpp
sound.cpp
Linking...

OGLCrystal.exe - 0 error(s), 0 warning(s)



So does that mean that I'm lucky that this application works?

[edit]
To give you an idea that I ran it and that it didnt crash:
[/edit]


  
Loaded 'C:\tmp\Release\OGLCrystal.exe', no matching symbolic information found.
Loaded 'C:\WINNT\System32\ntdll.dll', no matching symbolic information found.
Loaded 'C:\WINNT\system32\USER32.DLL', no matching symbolic information found.
Loaded 'C:\WINNT\system32\KERNEL32.DLL', no matching symbolic information found.
Loaded 'C:\WINNT\system32\GDI32.DLL', no matching symbolic information found.
Loaded 'C:\WINNT\system32\msvcrt.dll', no matching symbolic information found.
Loaded 'C:\WINNT\system32\OPENGL32.DLL', no matching symbolic information found.
Loaded 'C:\WINNT\system32\ADVAPI32.DLL', no matching symbolic information found.
Loaded 'C:\WINNT\system32\rpcrt4.dll', no matching symbolic information found.
Loaded 'C:\WINNT\system32\glu32.dll', no matching symbolic information found.
Loaded 'C:\WINNT\system32\ddraw.dll', no matching symbolic information found.
Loaded 'C:\WINNT\system32\dciman32.dll', no matching symbolic information found.
Loaded 'C:\tmp\ijl15.dll', no matching symbolic information found.
Loaded 'C:\tmp\BASS.DLL', no matching symbolic information found.
Loaded 'C:\WINNT\system32\winmm.dll', no matching symbolic information found.
Loaded 'C:\WINNT\system32\msacm32.dll', no matching symbolic information found.
Loaded 'C:\WINNT\system32\OLE32.DLL', no matching symbolic information found.
Loaded 'C:\WINNT\system32\mmdrv.dll', no matching symbolic information found.
The thread 0xB94 has exited with code 0 (0x0).
The program 'C:\tmp\Release\OGLCrystal.exe' has exited with code 0 (0x0).







[edited by - Xtreme on January 8, 2003 7:14:42 PM]
Yes! There are kangaroos in Australia but I haven't seen them...yet
null_pointer
null_pointer
quote:
I tried that and it runs fine, and the program does not crash.


A real world analogy:

You have a gun, a six-shooter with 3 bullets, but you have no idea in which chambers those bullets lie. You have just picked up the gun, put the tip in your ear, and pulled the trigger.

What do you think will happen with the next pull of the trigger?
Xtreme
Xtreme
null_pointer,

I know what you mean. Your saying that it may not crash now, but it may when you least expected it.

But my question is, if there was a bug,
then wouldnt the application come up with an Access Violation (0xc000000) or whatever?

[edited by - Xtreme on January 8, 2003 7:30:49 PM]
Yes! There are kangaroos in Australia but I haven't seen them...yet
Orikal
Orikal
quote:
I tried that and it runs fine, and the program does not crash.


I think what they are trying to get at is that your program might not crash, because there is data where you are trying to access it, but the way that you are handling your pointers allows other programs to overwrite that data. If they do, you will have logic errors.

Your program may run so fast or its memory may be secluded enough that other programs don''t get to your memory and botch it up, but if you use the "ptr = &obj" method extensively in a large program, I think you may find circumstances that are not so "lucky".
Xtreme
Xtreme
Here''s my analogy:

int s = 5;

int *t;

t = &s

So in this case, the program allocates memory for s to store "5", then you declare a pointer ''t'' of type int and in the 3rd line you store the address of where the variable ''s'' is.

So in my case,
I declare a pointer of type class and assign the address of the object that it created.
Yes! There are kangaroos in Australia but I haven't seen them...yet
Xtreme
Xtreme
Another question i have is, once you call the constructor of a class, doesnt that automically mean to initialise a class and return an object?
Yes! There are kangaroos in Australia but I haven't seen them...yet
kspbergstrom
kspbergstrom
quote:
Original post by null_pointer

A real world analogy:

You have a gun, a six-shooter with 3 bullets, but you have no idea in which chambers those bullets lie. You have just picked up the gun, put the tip in your ear, and pulled the trigger.

What do you think will happen with the next pull of the trigger?


The second person has a chance of 33.3% to die.

[edited by - kspbergstrom on January 8, 2003 7:51:37 PM]
DerekSaw
DerekSaw
quote:
Original post by Xtreme
int s = 5;

int *t;

t = &s


's' is not a temporary object, so in this case it is safe. What you are doing (in the 1st post) is something like this:
T *t = &T();


[edited by - DerekSaw on January 8, 2003 7:50:55 PM]
"after many years of singularity, i'm still searching n the event horizon" o

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.