PDA

View Full Version : c++ halp



PrivateParts
Mar 29th, 2009, 04:51 AM
ok. So im having a problem with a destructor in c++

I have a myString class. Which uses character arrays to create strings.
it has overloaded operators to do manipulation on character arrays.

in myString class i have private member variables int _length which gets the length of a dynamically allocated array, and a char *_ptr which points to the char array

So the class isnt doing much. the destructor just does

delete [] _ptr;
_ptr = NULL;



Now. I have a CProduct class which uses myString.
The private member variables in it are myString _id, myString _name, etc

I need a destructor in this class too.

i am trying to do

delete [] _id;

etc etc in this destructor. But i get a error:

Error 1 error C2440: 'delete' : cannot convert from 'myString' to 'void *' o:\comp 252\labs\lab10\mystring\mystring\cproduct.cpp 73


I cant figure out how to fix this.. havent seen an mention of it in the book im using thus far.

I need to be able to do the delete on _id and what not (or just a delete *this) so im not filling up the heap



halp me koob

Koobazaur
Mar 29th, 2009, 11:12 AM
First of all, your mString constructor should be:



if( _ptr != NULL )
{
delete [] _ptr;
_ptr = NULL;
}


You might get some nasty unpredictable effects if you try to delete a NULL pointer, AFAIK.
Also make sure your _ptr gets set to NULL in your constructor otherwise it will get a gibberish value and, when deleted, cause memory corruption.

Now onto your main problem - you gotta learn to read your error messages PP!

delete [] _id;
Error 1 error C2440: 'delete' : cannot convert from 'myString' to 'void *'

What is the error telling you? It expects a pointer (void *) but you are feeding it a... NOT pointer. You're feeding it a myString member variable which has NOT been allocated dynamically. Hence, you cannot call delete on it.

So what do you do in this case?























Nothing.


You see, your CProduct object has a myString _id; NOT myString* _id. Your _id is not a pointer, but a statically allocated variable that is created whenever a CProduct object is created. When CProduct is destroyed, it will destroy all of its members, which willl automatically call their destructors - including your _id and other myStrings.

That is part of the reason to use OOP and encapsulation - once you get your myString class working, you don't have to worry about what it does on the inside, it should be able to take care of itself!

I think you were confused with when a destructor gets called, thinking you need to explicitly called a "delete," which is not entirely true.

A destructor gets called whenever an object is destroyed.

when is an object destroyed? there are few, pretty logical ways, depending on how it is created, for instance:
* If it is statically allocated inside a function, then it will get automatically destroyed when the function ends.
* If it is dynamically allocated via new, it will get destroyed when you manually call delete on its pointer
* If it is a member of another class, it will get automatically destroyed whenever the object of that class gets destroyed (for the same reasons as above). <-- this is your scenario here with CProuduct and its member _id!

Basic rule of thumb: If you're not creating an object view "new", never, EVER call delete on it. It will get destryoed automatically at a logical point (outlined above).

In your case, your myString will clean itself up in the destructor, so you don't have to worry about it. Your CProduct, which has myString as member vars (not dynamically allocated), will automatically destroy them when it itself is destroyed, so you're good. All you have to worry about is making sure a CProduct object gets properly destroyed (i.e. call delete if you called new), and everything will be taken care of.

So, in a nutshell, here is what would happen if you destroyed your CProduct object

* CProduct is being destroyed
* CProduct calls its destructor
--> CProduct now automatically destroys all of its member vars
---> _id is being destroyed
----> _id calls its destructor, deleting its _ptr, cleaning up memory
---> _name is being destroyed
----> _name calls its destructor, deleting its _ptr, cleaning up memory

For more info, check out this: http://www.parashift.com/c++-faq-lite/dtors.html



or just a delete *this


DONT do this (also it should be delete this not delete * this). If your object is not created via new it will explode. also, after you call it, the object becomes invalid so if you do it inside its own function and the function tries to access its member vars, boom. Also a destructor is called when you do a delete on a pointer, is if you put "delete this" in a destructor - infinite loop.

Face
Mar 29th, 2009, 04:01 PM
10 INPUT "What is your name: ", U$
20 PRINT "Hello "; U$
30 INPUT "How many stars do you want: ", N
40 S$ = ""
50 FOR I = 1 TO N
60 S$ = S$ + "*"
70 NEXT I
80 PRINT S$
90 INPUT "Do you want more stars? ", A$
100 IF LEN(A$) = 0 THEN GOTO 90
110 A$ = LEFT$(A$, 1)
120 IF A$ = "Y" OR A$ = "y" THEN GOTO 30
130 PRINT "Goodbye ";U$
140 END

PrivateParts
Mar 29th, 2009, 05:04 PM
With myString class i had put a cout in the destructor to see when it was destroying objects.

If i do something like obj1 = "Testing" (uses a one param constructor that has a char array as its argument) and then do obj1 = "Testing 2" , it does a destroy.

What i was getting thrown off by is if i change the values in an object for CProduct in the same way it wasnt spitting out this cout message.. forgot i commented out that cout so thought it wasnt destroying when i would reintalize something.
Thought they werent getting destroyed so the heap was filling up


One more thing though. In my default constructor for CProducts i figured i would set _id and what not to NULL. Though it crashes if i do. This because _id isnt a pointer? The book (what ive read atleast) hasnt really talked about NULL.

Koobazaur
Mar 30th, 2009, 02:54 AM
Correct. NULL is reserved for pointers.

Or rather, should be. In reality, NULL is not a built in C++ type but usually a define somewhere (for instance in windows.h if you're usign that). Most likely it is simply set to 0. Meaning, you can set it to an integer. But you shouldn't since it will be confusing for other people who read your code.

(Also, FYI, setting a pointer to NULL or 0 will usually have the same effec, since NULL is most likely 0. You should stick to using NULL instead of 0, though, since it may in fact be platform dependant, and different platforms may define NULL differently).

If you want to nullify a string, simply give it a function like Empty() which empties it out and another IsEmpty() which returns true if the string is empty (i.e. length == 0 or _ptr == NULL ).

Also I would advise against your CProduct setting _id to NULL i.e. "empty" Instead have the myStrings set themselves to be empty when they are created. Again going back to what I was saying earlier - the objects should take care of themselves as much as they can. This way you don't have to worry about low level stuff when you're coding high level stuff.

PrivateParts
Mar 30th, 2009, 03:45 AM
Thanks

Another question though.

I pretty much have my two classes implemented. I can load up a wack of product objects from a txt file

What i need to do now is create 2 arrays of pointers which will point to the elements of a Cproduct array

"Application will manage the order of the array of products by using 2 arrays of pointers that will be pointing to elements in the array of products"

"There should be 2 arrays of pointers, one so that the array is in id order, the second so the array is in product name order.

Code a sort function that will first set the array of pointers to point to each element in the array of objects (the address of each of the elements), then this function will sort the 2 arrays of pointers (note that the array of products does not change only the pointers are swapped) "


ie:
CProduct products[10]; //my product array (works fine. i can load data into it from file)

typedef CProducts* IntArrayPtr;
IntArrayPtr *pToProduct = new IntArrayPtr[10]; //one of them

I can make pToProduct point to products by: pToProduct[0] = &products[0]; (though would use a loop to do all the pointing)

This question isnt demonstrated in the book or my instructors powerpoints so i have absolutely no idea how i get the _id only out of pToProduct so i can do some sort of comparison for a sort...

or would i really need to get at id/name through the array of pointers. suppose since they are being set in the same order as the array of products from the get go i could try doing my comparison with my products accessor functions and sort the arrays of pointers based off that.

Koobazaur
Mar 30th, 2009, 06:05 AM
typedef CProducts* IntArrayPtr;
IntArrayPtr *pToProduct = new IntArrayPtr[10]; //one of them


Why not just do this:



CProduct* pToProduct[10];


since your product array is always 10 anyway


As for comparing, if your CProduct's _id is public you can just compare it directly. If it's not just give it something like:


//note this returns const reference - important for efficiency!
const myString& GetID() const
{
return _id;
}


And use that in your sort like this:




//referencing the pointer to the product using ->, 'x' is a random element you want to get
pToProduct[x]->_id; //only if _id is public, OR:
pToProduct[x]->GetID(); //probably much safer



Now you have all you need to do the sorting. If you are required to fill out your array of pointers first, bubble sort sounds like a good choice here. Google it, it's pretty simple.

Also, there are a few sort functions in the standard c++ library, but I am guessing your prof / book does not want you using them here.

EDIT: btw, "pToProduct" is a horribly confusing and misleading name. I'd call it "productPointersSortedByID" or something like that.

EDIT: also "IntArrayPtr" is bad too, sounds like the type is a pointer to an array of integers. I'd call it "CProductPtr." Or just skip doing the typedef altogether, simply " CProduct* " is clear enough.

PrivateParts
Mar 30th, 2009, 02:53 PM
Why not just do this:



CProduct* pToProduct[10];


since your product array is always 10 anyway


As for comparing, if your CProduct's _id is public you can just compare it directly. If it's not just give it something like:


//note this returns const reference - important for efficiency!
const myString& GetID() const
{
return _id;
}


And use that in your sort like this:




//referencing the pointer to the product using ->, 'x' is a random element you want to get
pToProduct[x]->_id; //only if _id is public, OR:
pToProduct[x]->GetID(); //probably much safer



Now you have all you need to do the sorting. If you are required to fill out your array of pointers first, bubble sort sounds like a good choice here. Google it, it's pretty simple.

Also, there are a few sort functions in the standard c++ library, but I am guessing your prof / book does not want you using them here.

EDIT: btw, "pToProduct" is a horribly confusing and misleading name. I'd call it "productPointersSortedByID" or something like that.

EDIT: also "IntArrayPtr" is bad too, sounds like the type is a pointer to an array of integers. I'd call it "CProductPtr." Or just skip doing the typedef altogether, simply " CProduct* " is clear enough.


Ah yea, i didnt have my gets as const reference. I tried using pToProduct[x]->getID() before but wasnt getting anywhere. changed it and its working now.

Also the naming conventions here, i was copy and pasting a bit from my instructors power points. So yea, intarrayprt isnt good.

I used CProduct *pointToID[10] and *pointToName[10]

We need to code our own sort. I will work on that today and hope it goes smoothly..

Koobazaur
Mar 30th, 2009, 03:13 PM
Also the naming conventions here, i was copy and pasting a bit from my instructors power points. So yea, intarrayprt isnt good.



WTF what is wrong with your instructor? I really want to ask him what the hell he was thinking naming it that...



We need to code our own sort. I will work on that today and hope it goes smoothly..

Like I said, most sorts are actually really simple in principle once you understand how they work. Google is your friend here.

PrivateParts
Mar 30th, 2009, 03:29 PM
My instructors notes have always been horrible. Has made it a pain in the ass trying to learn from her in VB and C++.

Notes off the blackboard are horrible too. She'll start writing something in one spot in a certain color, draw some boxes and lines between them to show memory locations, start writing in a different color elsewhere on the board and so on. Makes it hard to make understandable notes.

Anyway, ive coded a few sorts before so i should be able to get it done

PrivateParts
Mar 31st, 2009, 02:00 AM
my search, sort, and a few other functions ive done work fine.

Though im not getting something again.

Allow a product to be deleted
The deleting removes the object (ie move up the last item in the array to the location of the deleted item and reduce the size of the array) remember to again call the sort to reset the addresses in the pointer arrays and then sort them.


Thing is we are suppose to use a fixed size for all the arrays in the app. So when i first load up the array of cProduct from file i have a numberUsed counter that keeps track of how many products ive actually added (i filled in 9). So the last object in the array is set up with data from the default constructor (nothing but zeros)

Then my setting up the arrays of pointers, sorting and searching uses that numberUsed to as a limit in any loops i need to do.


Anyway.. i would assume i would need to decrease my numberUsed by 1 while doing a 'delete' on the object so i could still use my functions fine. But would i really be doing a 'delete'? Or just copying over whats in the object with the next object in the array.

Not sure how i would delete it otherwise.. its whats in the array of products i need to kill.

PrivateParts
Mar 31st, 2009, 03:21 AM
I ended up just doing it like that.

Koobazaur
Mar 31st, 2009, 05:57 AM
Sounds like you got a the right idea. Just copy the last element into the place of your "deleted" element and decrease numberUsed by 1. Also make sure you handle a case where you only have 1 element left. Also remember to re-create the pointer arrays since you will still have pointers pointing to the last (now unused) element.

FYI, this is a pretty standard thing that you often use when working with a fixed sized memory block or array of some sort that adds / removes data frequently. The little bit of memory waste is preferable to constantly deleting and reallocating the exact amount of memory. IIRC, a lot of the standard C++ library template containers (like vector) work on this exact principle.

PrivateParts
Mar 31st, 2009, 06:33 AM
yea i reset the pointer arrays when ever i did an add or 'delete'
pretty much finished the project. Its about 23 pages long so far.
fucking thing is only worth 6%.

Just need to create a few 'reports' which print out to files any exceptions thrown, and a report that just outputs in the same way my input file was done but with some totals at the bottom for total inventory, unit price, sell price..

This was suppose to be a two person project but unfortunately my partner is clueless at c++.

He keeps saying he has three buddies who graduated in programming courses who are helping him so the project will be done tomorrow (when its due) regardless.

Im starting to wonder. And get a little annoyed that ive done this whole thing myself.
With some very helpful hints from you ofcourse.

I think i should be fine for the remainder, though was curious if there is a clear screen function in c++?
I used switch statements to create menus and thought it would look nicer if the display was 'reset' rather than scrolled down.

Koobazaur
Mar 31st, 2009, 07:47 AM
I think i should be fine for the remainder, though was curious if there is a clear screen function in c++?

http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.20

on windows, you can just do system("cls"); which is defined in stdlib.h IIRC.

PrivateParts
Apr 1st, 2009, 02:19 AM
My lab partner helped.. he printed out the cover page.

Glad this day is over. didnt get a chance to study for either quiz though. Got 68% on one (which isnt great for me but probably not too horrible since i havent even glanced at the material yet or paid attention in class for the last 2 weeks) and no idea on the other.

Happy the projects are out of the way though. Probably wouldnt have finished on time without the helpful hints.

I am sort of curious as to what happen with my lab partner and his 3 buddies working on it... i never did see a copy of it..