The traditionally held restrictions of malloc()-allocated objects are “no constructor calls” and “no destructor calls”. However, there is an additional restriction: no virtual functions or polymorphism. If you wish to implement polymorphism on the Arduino and plan to use dynamic memory, you must declare operators new and delete (in terms of malloc() and free()) before you can use polymorphism. Once declared, these operators acquire the “magic” they are known for.
Attempting to call a virtual function on a malloc()-allocated object on the Arduino will not crash in an obvious way. It will merely return a bogus result which appears to come from some random spot in memory (maybe where the function points).
Of course, if you’re developing for a normal platform and not a microcontroller, just use the native new and delete and be done with it.