I'm saying it's not self-documenting.
O_o
The convenience of self-registration outweighs the cons when properly implemented.
If you know the API is self-registering, it is self-documenting.
I mentioned delete what you new because obviously I did not know Qt does something as insane as automatically destroying objects because it isn't self documenting.
Do you really not realize that the facility in question is acting as a collection of smart pointers with a strict owner?
It is, very literally, a variant of the mechanism employed by the "Boost Pointer Container Library" which I know you love.
The only difference is that this facility, as implemented, uses inheritance based polymorphisms without support of template based polymorphisms.
The act of creating the object in question as a child of another object is only registering the child object with the container.
Now, you didn't know the API is self-registering; none has faulted you for not knowing.
However, the mechanism at play is very useful and has few negatives.
Again, I appreciate that this is a "knee-jerk" reaction, but like the other things you've grown from in the past, this is something you should put in your toolbox.
[Edit]
If you are having difficult understanding the value of self-registration, feel free to continue reading.
If you already understand the value, you should probably just have a cookie.
What happens when `s' goes out of scope? If `s' is a value type, it living beyond its scope is repellent. The `new' object at least is expected to live beyond the pointer's scope.
We can conquer this by requiring that `s' live beyond the implied scope.
Code:
class MyWidget
// ...
Button m; //m(this);
// ...
We still have the same problem of managing ownership.
The `MyWidget' instance owns any `m', but the abstraction of underlying facilities requires that `m' be referenced by the underlying primitives.
We can conquer this by using a shared pointer.
Code:
class MyWidget
// ...
Pointer<Button> m; //m(new Button(this));
// ...
There is now the issue of lifetime in relation to events that must be considered: if the widget represented by `MyWidget' is destroyed, for example say by the user clicking a "close" button, should the GUI resourced owned by `m' not be reclaimed by the system?
(This could be done without destroying the object, but a function and object would still need to be registered as a callback using any available mechanism.)
We can conquer this by moving ownership to a registry.
Code:
Widget * s(CraftWidget<Button>(this));
In standard ISO C++, at least before more of C++11 is readily available to the majority of clients, we don't have a good way of forwarding arbitrary information to the `Widget' without borrowing heavily from factory techniques.
We can conquer this by moving passing a pointer to a new element to the registry.
Code:
RegisterWidget(this, new Button(/*???*/));
We now need to query the registry to retrieve the object we just created or store the object separately.
Code:
Button * s(new Button(/*???*/));
RegisterWidget(this, s);
We now have a process requiring multiple parts so we can't easily use the facility as part of the initialize list.
We can conquer this by return a pointer to the created item as part of the registration.
Code:
Button * s(static_cast<Button>(RegisterWidget(this, new Button(/*???*/))));
We now have to duplicate the type information.
We can conquer this with ISO C++98 templates.
Code:
Button * s(RegisterWidget<Button>(this, new Button(/*???*/)));
Oh, wait, we actually can't get rid of the duplicate type information and still allow for arbitrary construction with C++98 templates.
The best we could do is allow a fixed set of parameters and simply forward them, process a list of types and forward the expansion (which is valid even with inheritance based polymorphisms because it is the constructor we are making a template), or use a serialization, like "JSON", for all construction information.
We also can't conquer this without templates.
Code:
Button * s(static_cast<Button>(this->registerWidget(new Button(/*???*/))));
Here we are back to having duplicate type information.
*shrug*
I could go on for much longer than anyone would read.
The point is: performing an action related to an object provided as part of construction, managing resources as a list of resources, strict ownership, and smart pointers are all perfectly valid.
They are not less valid, or less useful, simple because they've been used together.
[/Edit]
Soma