Why is using the assignment operator on a dereferenced pointer to a purely abstract interface not a compiler error? When could this ever be useful? It seems like it can only lead to subtle bugs as I've outlined below.
In order to have a globally accessible object, which implements an interface, with a default value, that I can later override, do I have to use a handle (pointer to a pointer -- or -- pointer to a std::unique_ptr), or is there another approach?
#include <iostream>
class Interface {
public:
virtual int Value() = 0;
};
class Implementation : public Interface {
public:
Implementation(int value) : value(value) {}
int Value() override {
return value;
}
int value;
};
// Set default value
Interface* object = new Implementation(1);
Implementation* object2 = new Implementation(2);
int main() {
// Why is this line not a compiler error?
*object = Implementation(3); // Try to override default value
*object2 = Implementation(4); // Override default value
// This outputs "14", not "34", why?
std::cout << object->Value() << object2->Value();
return 0;
}
To get around these issues, as well as allow setting the overriding the default value in unit tests, I have gone with the following approach.
// Set default value
static std::unique_ptr<Interface> object(new Implementation(1));
void SetObject(std::unique_ptr<Interface> obj) {
object.reset(obj.release());
}
int main() {
SetObject(std::make_unique<Implementation>(2)); // Override default value
std::cout << object->Value();
return 0;
}
C++ objects by default get an operator= method generated by the compiler. This operator simply applies operator= to each of the member variables, and it is not virtual. That means it will work with the members of the static type of the declared pointer. Since Interface doesn't have any members, no members will be copied. Implementation has a member, so that member will be copied.
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