tags:

views:

250

answers:

8

hi guys, i have got all but one last instance. here's my code:

void main()

    {

        Animal bozo("Bozo", 408, 400); // name, cagenumber, weight

        cout << "This animal's name is " << bozo.getName() << endl;

        bozo.destroy();


    }

i've declared the class for Animal and functions like name, cageno and weight. as the qns requires the last function "destroy", i'm really stuck with how to define it.

its a void so i cant return. i think it should be a delete[] but i am stuck defining it.

any help?


i am given the codes from void main() part, and i am required to write the application to use class Animal.

here's my code:

#include <iostream>

using namespace std;

class Animal
{
public:
    // constructor
    Animal(char* name[20], int cagenumber, int weight)  
    {
     new_name = new char[strlen(name) +1];
     strcpy(new_name, name); // string copy to set the name
    }
    // destructor
    ~Animal() 
    {
     delete[] new_name;
    }
    // functions
    char* getName() { return new_name; }
    int getCagenumber() { return cagenumber; }
    int getWeight() { return weight; }

protected:
    char* new_name;
    int cagenumber;
    int weight;
};

void main()
{
    Animal bozo("Bozo", 408, 400); // name, cagenumber, weight
    cout << "This animal's name is " << bozo.getName() << endl;
    bozo.destroy();

}

basically if i comment out bozo.destroy, everything's working fine, otherwise, it errors.


dang. my tutor said to ignore the destroy function altogether since its function was not mentioned n the qns.

sorry for the trouble guys.

+2  A: 

A destructor in c++ is defined as

~ClassName()

not sure wether you can call it directly.

However you are creating your animal instance on the stack via an initializer and not on the heap via new. When declaring on the stack, there is no need to pop it from the stack at the end of the current scope, the compiler will do it for you.

When allocating Animal on the heap via new Animal() make sure to free the memory for it using delete instanceOfClass This will also call the destructor for you.

Johannes Rudolph
You can call the destructor directly, but really shoudn't since it will be called again when the object goes out of scope and this can cause problems.
sharptooth
In fact, you MUST call the destructor for objects constructed using placement new, but this is not the case here.
Gorpik
A: 

Delete will be called automatially, so the destroy can be anything even an empty method.

void Animal::destroy() {}
grigy
Destructors are a tilda followed by the class name.
Martin York
I know, but my version of destroy is not a destructor
grigy
destroy in my qns is a function, might not necessary be a destructor.
RealiX
A: 

You can delete your new_name array in the destroy function, that is, change you code in the way, that the destructor will be an empty function, while destroy will clear all of your class allocations. Not sure why C++ question will require such an approach instead of using destructors.

Just define in your class:

void Animal::destroy() 
{
     delete[] new_name;
}

and leave the destructor empty:

~Animal()   
{
}

While it's really not the standard approach, it will do the job either

Nava Carmon
+2  A: 

As other pointed out, using a destroy method is a bit pointless, you should just define the destructor ~Animal, but if you absolutely need to implement it, I would do

 [...]

 void destroy() {
     delete [] new_name;
     new_name = NULL;
 }

 ~Animal() {
     destroy();
 }

 [...]

This is a rather bad design though. In general, you should strive to only release (member variable's) memory in the destructor. That way you're guaranteed pointers are valid in all other functions.

By adding such a destroy function, every other function has to check for a valid new_name pointer before dereferencing it...

Pieter
Yes, could be an inappropriate attempt at early resource release, for an object the client knows won't be used again, but which isn't yet out of scope. This might be appropriate if for instance you had a socket object, and it had some resources encapsulated as class ThingsASocketNeedsWhileMakingAConnection. Once the socket is connected, it wants to discard all those, but it might also want to embed a TASNWMAC in the socket object. So have a destroy function: client's responsibility not to use the object again...
Steve Jessop
... and if you don't want to place that responsibility on the client, call it `reset()` instead of `destroy()`, and make sure all the other functions still work if it has been called.
Steve Jessop
i think im going to stick with this method since it doesnt really change the qns much. one thing i'd like to know, what is the purpose of new_name = NULL?
RealiX
deleting a NULL pointer does nothing according to the C++ spec, deleting a pointer twice however, invokes undefined behavious (you'll probably crash). A destructor is always called for stack objects. So if you wouldn't set the pointer to NULL, you would get a crash when an Animal object goes out of scope if you called destroy...
Pieter
A: 

You decided to manage a dynamically allocated array by yourself. If you do this sort of thing you have to consider the rule of three. There's no need to add another "destroy" function. That's what the destructor is for. You should not invoke the destructor explicitly unless you know exactly what you do. (There are use cases where this makes sense but it's not something a beginner should care about.) The destructor is invoked automatically for "automatic" objects (those that live on the stack) whenever they go out of scope. It's also called automatically if you delete a heap-allocated object.

But in your case it's much more convenient to just use std::string for the animal's name and be done with it. If you use std::string as a member you won't need any user-defined copy constructor, assignment operator and destructor because the compiler-generated ones are perfectly fine. In general, you should prefer STL containers and std::string as member objects over pointers, when possible. It makes resource management much simpler.

#include <iostream>
#include <string>

class Animal
{
public:
    Animal(std::string const& name, int cagenumber, int weight);
    virtual ~Animal() {}

    std::string getName() const { return name; }
    int getCagenumber() const { return cagenumber; }
    int getWeight() const { return weight; }

protected:
    std::string name;
    int cagenumber;
    int weight;
};

Animal::Animal(std::string const& n, int c, int w)
: name(n), cagenumber(c), weight(w) {}

Note also, that I added the const qualifier to all member functions because they don't change the object's state. This way someone who only has a const reference or pointer to such an object gets to use these functions, too.

The use of "protected" suggests that you want to use Animal as base class in a class hierarchy. In that case you should not forget to make your destructor either protected or public and virtual. If you intend to delete polymorphic objects through a pointer to their base class the base class must have a virtual destructor. Otherwise, you get undefined behaviour.

sellibitze
A: 

Just leave out bozo.destroy().

Your variable lifes on the stack and is automatically destroyed when main() is left. (You can see it by putting a breakpoint into your destructor's code.)

rstevens
bozo.destroy() is part of the qns. i will i could remove it and everything would work fine.
RealiX
A: 

Solution A: Use scope to manage lifetime:

int main(int argv, char **argv)
{
    if(argc==2 && strcmp(argv[1],"animaltest")==0)
    {
        Animal bozo("Bozo", 408, 400);  // name, cagenumber, weight
        cout << "This animal's name is " << bozo.getName() << endl;
    }
    /* bozo is nonexistent here */
}

Solution B: Use new and delete for bozo:

int main()
{
    Animal pBozo = new Animal("Bozo", 408, 400); // name, cagenumber, weight
    cout << "This animal's name is " << pBozo->getName() << endl;
    delete pBozo; pBozo = 0;
}

Hint: Use strdup() for copying C-style strings. Hint: Use initializer list for initializing members in constructors when possible.

Notinlist
Another hint: use std::string instead of C-style strings when you can. If you're taking a class on C++, they should be covered first.
David Thornley
A: 

You used void main(). The main() function returns int, not void (C++ Standard, 3.6.1, paragraph 2). Any book or person who tells you anything else is not dealing with standard C++, and is likely unreliable on other things. I'd suggest finding a more accurate book on C++. There have been StackOverflow questions that you might find helpful, like Good book to learn C++ from? and The Definitive C++ Book Guide and List.

David Thornley