Thanks for the explanations. I am in a context where the same programmer writes the code on both sides of the call to this constructor or methods, and thus can restrict the usage, which makes not necessary all the checks on the nul pointers or other inventive user tricks. Though I know that testing the preconditions as much as possible is a key to writing robust code.
I should have figured out that it was a destructor : of course, java has this feature, but without this "~" convention.
void setup() {
Serial.begin (115200) ;
delay(1000);
message = new MessagePrinter;
if (message != nullptr) {
if (message->setString("test")) {
Serial.print("Success: ");
message->goPrint () ;
}
}
}
void loop() {}
If you're going to use dynamic memory anyway, why not use the String class? It'll handle allocation failures for you as well. I don't see the need to move the allocation out of the constructor, you can't return a bool, but you can still check if what == nullptr afterwards.
I stand by the claim that raw new/delete calls should be avoided whenever possible.
Case in point:
if (what != nullptr) {
delete what; // Uh-oh!
}
(It should be delete[] what.)
(You don't have to check for nullptr first, you can call delete[] nullptr without any problems.)
Writing with String class was my first approach. I met some nasty problems with that class, like for example the blocking "readString" method, which made me browse here and there and I found that, especially in a real time context on a system with a small memory for the heap and no garbage collector, instantiating many times String objects with different sizes would create such a swiss cheese in the heap that the application would rapidly crash. This is why, following these advice, I went to programming with the old "C" style character array methods, which doesn't presume dynamic allocation. Same for my tasks, which are classes, I will avoid to intensively use "new" - "delete", to avoid the same swiss cheese problem : instead have a pool of persistent tasks, of which perhaps half or more are in a sleeping state until for some reason one is needed and then raised to running state.
gfvalvo:
Rather than saving a pointer to the passed string, the code I posted makes a copy of the string. I did this because you don't know what the user might supply as the string in your original code. If it's a local stack variable, it will cease to exist after the containing function ends and the pointer will no longer be valid. In fact, that memory will probably be used for something else. Run this example and watch what happens:
My code used dynamic allocation to get the memory to store the copy in. That may fail and return nullptr. The user needs to know this. But, you can't return a value from the constructor. So, I made a separate function that returns a bool for pass / fail.
~MessagePrinter() is the destructor. It cleans things up when the object's lifetime expires.
I don’t think that your class declaration will work.
You declare what as char constant thus the compiler won't allow you to change it.
abdelhmimas:
I don’t think that your class declaration will work.
You declare what as char constant thus the compiler won't allow you to change it.
The pointer is not immutable, the characters it points to are. const char * is a mutable pointer to immutable data, char *const would be an immutable pointer to mutable data.