I have a C++ static class with a method that creates an object. I would like to retrieve the object created by this method in a different function so that this new function takes ownership of the object. This is the code I have so far:
MessageBoxes.h
class MessageBoxes {
public:
static int info(const QString& message, const QString& title = _("Information"), QMessageBox::StandardButtons buttons = QMessageBox::Ok);
static int confirmation(const QString& message, const QString& title = _("Confirmation"), QMessageBox::StandardButtons buttons = QMessageBox::Ok | QMessageBox::Cancel);
static int error(const QString& message, const QString& title = _("Error"), QMessageBox::StandardButtons buttons = QMessageBox::Ok);
private:
static QMessageBox& createMessageBox(const QString& message, const QString& title = "", QMessageBox::StandardButtons buttons = QMessageBox::Ok);
};
MessageBoxes.cpp
QMessageBox& MessageBoxes::createMessageBox(const QString& message, const QString& title, QMessageBox::StandardButtons buttons) {
QMessageBox msgBox;
msgBox.setWindowTitle(title);
msgBox.setText(message);
msgBox.setStandardButtons(buttons);
return msgBox;
}
int MessageBoxes::confirmation(const QString& message, const QString& title, QMessageBox::StandardButtons buttons) {
QMessageBox m = createMessageBox(message, title, buttons);
return m.exec();
}
The problem is that at the line QMessageBox m = createMessageBox(message, title, buttons), the compiler tells me that the copy constructor of QMessageBox is disabled. This is fine, however I do not want to make a copy, I want to get the actual object that was created in createMessageBox. I declared the return type of createMessageBox as QMessageBox& assuming that it would return the reference but it doesn’t seem to work that way. Any idea how I can do that?
0) We don’t do this “static class” thing in C++. Those are hacks to deal with the fact that Java and C# force you to put all your code into classes. C++ does not do that, so we shouldn’t hack around a limitation that doesn’t exist. Classes are not storage places for code; they exist to define a data type. What you’re really trying to do is organize the code by grouping it under a common name; we do that with a
namespace.1) You may not return a reference to a local variable. References are for returning already-existing things.
2) You don’t want to return a reference, because the purpose of
createMessageBoxis to create a message box. You return a value: the message box that was created.3) When you write
Foo bar = something();
the result from
something()is copied, even ifsomething()did happen to return a reference to an already-existing thing. This is because the type ofbarisFoo, and notFoo&.barmust hold its ownFoo; it cannot refer to one, because it isn’t a reference. And since theFooreturned bysomething()is a value in its own right, with its own location in memory, we can’t just cause it to “be”bar; the program must make a copy.To refer to the result from the function, you would write
Foo& bar = something();. This will extend the lifetime of the returned object (which ordinarily would go out of scope right away), so there is no problem with referring to a temporary.4) However, optimizing compilers are smart, and this is unlikely to gain you anything. If you just return a value and assign by value, chances are good the copy will not actually happen (although the Standard says in effect that your code must be prepared for that possibility).
5) Dynamic allocation is, honestly, a really bad idea here. If you must do it, at least use some kind of smart-pointer wrapper. Although, when your copy constructor is disabled, sometimes you’re stuck with this sort of thing. :/