I'm very troubled by the behavior of calling operator= with polymorphism. Very unfortunately, it follows the same pattern as all other virtual functions...
I solved it partially on line 53, but what about the fourth output? How can this be fixed or avoided? I was originally under the impression that the operator= function got special treatment like constructors and destructors, but now I am left with dozens of memory leaks/corruptions...is it a design flaw that I need to do this at all? How can I make sure that all operator= functions along the inheritance tree are called in these cases?
I will have to check tomorrow @ work, but I am very troubled by this too!! I was under the same impression as you. These are my classes for my own test:
template<class T>
void Display(const T &val)
{
std::cout << val << std::endl;
}
class Base
{
public:
Base() { Display("Base: Default constructor."); }
virtual ~Base() { Display("Base: Destructor."); }
virtual Base& operator=(const Base& op2)
{
Display("Base: Operator =().");
return *this;
}
};
class Derived : public Base
{
public:
Derived() : Base() { Display("Derived: Default constructor."); }
virtual ~Derived() { Display("Derived: Destructor."); }
virtual Base& operator=(const Base &op2)
{
Display("Derived: Fix for Operator =().");
//With this "solution" we are eternally bound to RTTI.
operator=(dynamic_cast<const Derived&>(op2));
return *this;
}
Derived& operator=(const Derived& op2)
{
Base::operator=(op2);
Display("Derived: Operator =().");
return *this;
}
};
As you can see, it sucks. The only way to ensure proper operation is to use a dynamic_cast<>() in the override, which bounds this method to always depend on RTTI, meaning no optimization by removing RTTI ever again. Plus it is a lot of effort: Override the base operator, then create the new operator, and make sure the base implementation is called.
Are you sure you can't use this as a Derived* in here? Sure the function is taking and returning Base&, but it's part of Derived here, isn't it? (I haven't checked this though so I could be wrong).
The code running as operand 1 (or left-hand side operand) is for sure of type Derived. The problem comes with operand 2 (or right-hand side operand). What guarantees me that it is of type Derived too? The only safe way out I could see was a dynamic_cast. :-(
The problem is, if I have two Base references to derived types, and I do BaseRef1 = BaseRef2, how can I make all operator= fire down the inheritance tree based on the derived type referenced?
Well, I read the post, sloppy9. It is very enlightening, no doubt. But it is also an eye-opener. I just can't shake the feeling that this is the first-ever BUG in C++. Probably most of you disagree in calling it a bug, and it is not that I am categorically stating this is a BUG, but it sure feels like it.
I understood the reasoning of using non-leaf abstract classes for sure, but that may very well be super impractical in large object hierarchies, and I really don't see me repeating blocks of member variables just to keep bases data-less. I know, there are ways (use a struct, leave fields in base but assign in concrete, etc.).
Yeah, I need all the data in the entire inheritance tree to be copied, between the uppermost base classes (including multiple inheritance) to the fully derived type.
@Sloppy9: Thanks! I'll be using the dynamic_cast method, as as firedraco said, I would like to be able to assign through references/pointers.
My feeling is that operator=() isn't really appropriate for polymorphic entities. They are by definition different types so it doesn't make sense to make one subtype equal to another subtype. They are by definition not equal, therefore we need more of a cast than an assignment.
So if I have:
Base<-Der1;
Base<-Der2;
Base& b1 = Der1;
Base& b2 = Der2;
Then doing b1 = b2 doesn't really make sense. What might make more sense is:
Der2& d2 = (Der2) b1; // Need to know the types and do proper conversion
The only time the assignment makes sense is when b1 and b2 refer to the same derived type. But the whole point of polymorphism is that the programmer doesn't need to know the derived type.
Hi , all i sorry for my lack of knowledge but i am not able to understand the problem .. compleatly .. i will be thinking over it ..
thanks all of you .. .