Do we need to delete the objects?

I know, if we create object to PT(…) or CPT(…) pointer, we could care nothing about the deleting of this object.

However, if we create object to general pointer, do we need to delete it?

It seems we need to delete it, is it right?

I’m not sure what you mean. “object to general pointer”?

You need to look if the class inherits from ReferenceCount. If it does, then use smart pointers, if not, use regular pointers and manage the deletion yourself.

You should never attempt to delete an instance of a class that inherits from ReferenceCount.

I see, Thanks!

My further question is, if we construct global object with static function, do we need to delete them?

For example, in the code below, do we need to delete myHandler?

EventHandler* myHandler = EventHandler::get_global_event_handler();

...

//after the final using
delete myHandler; // do we need to write this?

Do not delete that object.

You didn’t actually create it, you only retrieved the pointer to the (already created) global instance. You should not delete that pointer.

David

Is that true for all other global instances?

By the way, if we want to handle “mouse1” event in our own method, it seems that we can use EventHandler::add_hook(“mouse1”,…); is this the simplest way? Where is the default handler of “mouse1” event?

If you call a get_ method like get_global_ptr, that kind of implies that you don’t get ownership of the pointer. If it would be called make() or so, then it’d be different.

This is the correct way to handle “mouse1”. There is no default handler. (The default behavior is to do nothing.)

David

Thanks :smiley:

For the codes below, do we need to delete the instance of GenericAsyncTask?

taskMgr->add(new GenericAsyncTask("Control Neck", &turnHead, (void*) NULL));
....
framework.main_loop();
....

//framework.close_all_windows();
framework.close_framework();
return (0);

In my opinion, it seems should be:

GenericAsyncTask * task = new GenericAsyncTask("Control Neck", &turnHead, (void*) NULL);

taskMgr->add(task);
....
framework.main_loop();
taskMgr->remove(task);
delete task;
....

//framework.close_all_windows();
framework.close_framework();
return (0);

Is it right?

No, you should not delete this object. Because it inherits from ReferenceCount, it will automatically delete itself when the reference count decrements to zero. If you explicitly call delete, you will delete it twice, which will cause a crash.

Also, because it inherits from reference count, you should store it in a PT(GenericAsyncTask) object instead of a GenericAsyncTask* pointer:

PT(GenericAsyncTask) task = new GenericAsyncTask("Control Neck", &turnHead, (void*) NULL);

taskMgr->add(task);
....
framework.main_loop();
taskMgr->remove(task);
....

//framework.close_all_windows();
framework.close_framework();
return (0); 

David

Do you mean if the class inherits from reference count, we can construct its instance as parameters directly and do not need to delete them.

For example, the code below will destroy the “task” parameter by itself:

taskMgr->add(new GenericAsyncTask("Control Neck", &turnHead, (void*) NULL));

Is that right?

Yes, that is also correct.

Please see the codes bleow:

NodePath ambientLight = render.attach_new_node(new AmbientLight("ambientLight"));

DCAST(AmbientLight, ambientLight.node())->set_color(Colorf(.1,.1,.1,1));

......

/*then, I try to get the color of ambientLight, however, I use different Class Type this time, the result is different from what I had set. Why?*/

Colorf color = DCAST(Light, ambientLight.node())->get_color();

When I watch the value of color, it is very strange, seem like {0,0,3.4e-44,0}, what is wrong?

You are cross-casting from PandaNode to Light, which is not supported by C++ (Light does not inherit from PandaNode). Because of this, you are computing the incorrect pointer value.

Instead, you should cast to LightNode.

David

Then, how about DirectionalLight, PointLight, Spotlight?

Is there a general solution for multiple inheriting, i.e. can we feed DCAST() with dynamic Class Type? I am not sure about the background skills of DCAST.

These inherit from LightLensNode, rather than LightNode, so in case of one of these classes you need to cast to LightLensNode. It is a bit unfortunate that you have to treat AmbientLight differently from these other kinds of light objects, but that’s the nature of C++.

No. There is no general solution for this problem. You have to know at compilation time the full inheritance chain of the class, and DCAST cannot know that. All DCAST does is ensure (at runtime) that the object at least inherits from the class that you are casting it into, but it cannot check the actual inheritance path, and it cannot perform the pointer magic that the compiler will perform if you give it a properly related class.

David

It just need more lines for coding.

Can you tell us the difference about PT(Texture) array[10] and PTA(Texture[10]) array?

Is PTA(Texture[10]) a legal format?

How to express the following python variables in C++?

PTALMat4f[4]
PTALVecBase4f[16]
PTAFloat[16*4]
PTADouble[16*4]
PTAFloat[6]
PTADouble[6]
PTALVecBase3f[2]

:blush:

If you want an array of ten pointers to textures, you want PT(Texture) array[10]. PTA(Texture[10]) doesn’t make sense.

PTA is a reference-counted pointer to an array (or actually, an STL vector). So PTA(float) is an STL vector of floats, which is automatically deleted when the last reference goes away. The individual floats are not reference counted, just the overall vector. It is necessary that the typename that goes within the PTA() parens is not a reference-counted type, because it will be stored directly within the vector; so you cannot have PTA(Texture). (I guess you could have PTA(PT(Texture)), but I’ve never tried that, and I don’t know why you would want such a thing.)

The only reason to use PTA(float) instead of float array[] is when you want to pass around a reference-counting pointer to the array, for instance to store the array within an object and retrieve it again later.

Although I’ve been referencing PTA(float) in the above, there are a handful of predefined typedefs that are usually preferred. In the case of PTA(float), you should use PTA_float instead (which is defined in #include “pta_float.h”). The reason for using these typedefs is that they are set up to export from the DLL properly.

Also note that PTA’s don’t have an explicit size, unlike arrays. They’re STL vectors, so they dynamically resize; you can’t declare their size as part of the type.

The types you name are, respectively,

PTA_LMatrix4f
PTA_LVecBase4f
PTA_float
PTA_double
PTA_float
PTA_double
PTA_LVecBase3f

David