Real example is obviously much longer, but this sums up my problem:
class Object
{
int mInt1,mInt2;
Object::Object();
Object::Object(int param1);
Object::Object(int param1, int param2);
};
Object::Object(){}
Object::Object(int param1):mInt1(param1){}
Object::Object(int param1, int param2):mInt1(param1),mInt1(param2){}
Then in main:
if (type1){
Object instance(param1);
}
else{
Object instance(param1,param2);
}
// do stuff with instance
Whoops! That won't work, instance is out of scope for the program that follows.
Object instance;
if (type1){
instance = Object(param1);
}
else{
instance = Object(param1,param2);
}
// do stuff with instance
But now I run in to trouble because I didn't have a copy constructor defined. I'd really rather not write a copy-constructor because my actual class has dozens of members, many of which are non-basic types and might require even more work to copy.
Specifically, I am getting
main.cpp: error: use of deleted function ‘Object& Object::operator=(Object&&)’
instance = Object(param1);
^
note: ‘Object& Object::operator=(Object&&)’ is implicitly deleted because the default definition would be ill-formed:
The universal way to deal with non-copyable objects is to throw it into a unique_ptr (or auto_ptr, depending on your compiler).
std::unique_ptr<Object> instance;
if (type1) {
instance.reset(new Object(i));
}
else {
instance.reset(new Object(i, j));
}
Using raw pointers here really isn't safe because once you start having to deal with exceptions or any interesting code paths it becomes a chore to worry about leaks. Trust me, in 100% of cases, you will have less work and lines of code to deal with if you just drop it in a unique_ptr.
An optimal solution would be to redesign Object's constructors, because circumventing non-copyability may leave the object in an illegal state. In general, you want to preserve non-copyability if the compiler thinks it's necessary. We don't have the details here to flesh out such a solution however.
If you do not want dynamically allocation then you can use an Initialize function:
class Object
{
int mInt1,mInt2;
Object::Object();
Object::Initialize();
Object::Initialize(int param1);
Object::Initialize(int param1, int param2);
};
Object::Object(){Initialize();} //call the empty Initialize for nice coding...:)
Object::Initialize(){ }
Object::Initialize(int param1){ mInt1(param1); }
Object::Initialize(int param1, int param2){ mInt1(param1);mInt1(param2);}
Then you can use initialize to select the type.
Object instance;
if (type1){
instance.Initialize(param1);
}
else{
instance.Initialize(param1,param2);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With