Jake Jake - 3 months ago 7
C++ Question

Is it a bad design decision to manually call the destructor in the following case?

so I am currently working on my OOP/C++ skills and stumbled upon the following case:

I am making a game which is populated by entities, which have to eat in order to survive. They can either eat other entities or food. In order to achieve this behaviour I created an

edible
interface which forces every implementing class to create a
getNutritionalInformation()
method to calculate how saturated a unit will be after feasting.

So the whole thing is supposed to work like this code-wise:

std::unique_ptr<Entity> e1(new Entity);
std::unique_ptr<Entity> e2(new Entity);

std::cout << "Pre feasting energy: " << e1->getNutritionalInformation() << std::endl;
e1->eat(*e2);
std::cout << "After feasting energy: " << e1->getNutritionalInformation() << std::endl;


After this operation
c1
s energy should be higher than before, this value is currently randomly assigned during creation of an entity. But in order to simulate the death of the eaten entity I want to manually kill it while it is being eaten. I achieved this the following way:

void Entity::eat(Edible& subject) {
this->energy += subject.getNutritionalInformation();
delete &subject;
}


But in the end this simply seems kind of dirty to me, I would really like to let the smart pointer know in some way, that the object it currently holds/points to is not valid any longer. Is there a cleaner way to achieve this? I am pretty sure the way I am trying to do this is very hacky and not considered proper OOP programming.

Thank you for your help in advance.

Answer

Well, by e2 "eating" e1 it is actually taking ownership of it. Specifically, it has to take ownership of it, in order to destroy it. So the way to do it is actually this:

void Entity::eat(std::unique_ptr<Edible> subject) {
    this->energy += subject->getNutritionalInformation();
}

And... that's it. the subject will automatically be destroyed at the end of scope. In order to use this, you'll need to call std::move explicitly; this indicates that you are transferring ownership from the calling scope, into e2.

std::unique_ptr<Entity> e1(new Entity);
std::unique_ptr<Entity> e2(new Entity);

std::cout << "Pre feasting energy: " << e1->getNutritionalInformation() << std::endl;
e1->eat(std::move(e2));
std::cout << "After feasting energy: " << e1->getNutritionalInformation( << std::endl;

Note that after std::move has been called on e2, e2 can no longer be assumed to actually point to an entity (since ownership has been transferred).