Copy/move assignment can cause problems in actual code as follows:
void some_func( MyInterface* lhs, MyInterface* rhs ) {
*lhs = *rhs;
}
this is an example of slicing, but we are doing a nonsense slice assign.
In theory you can write a polymorphic assignment:
MyInterface& operator=(MyInterface const& rhs)const&{
AssignFrom(rhs);
}
virtual void AssignFrom(MyInterface const& rhs)const&=0;
but the situations where this makes sense are limited. Here are a few:
- This interface exists as a contract for a single fixed implementation. As such, standard assignment semantics are easy to implement.
- Assignment semantics are being replaced for this class because we are using the embedded sublanguage technique.
For cases other than this, sensible assignment at the interface level is difficult to justify, as if the two assigned objects disagree on their type, assignment is unlikely to give good semantics.
For the constructor case, no attempt to directly use a constructor of an abstract class can succeed already. Any use of the constructor will be in a context where there is an instance of a child class actually being constructed.
It is plausible that some work needs to be done -- some impurity -- in the interface. For example, if every instance of that interface needs to have its identity logged centrally, implementing constructors makes sense.
This is also a rare case.
In 999/1000 cases, =delete
ing them is the correct move. C++'s built-in object polymorphism doesn't play nice with assignment or copy/move construction. This is one of the reasons why people replace its use with versions that do play nice with it, like std::function
.