Re: Downcasting base-class objects to a derived-class
On Dec 6, 12:27 pm, vsk <vmi...@gmail.com> wrote:
bool Number::equals(IExpression &that) {
if (typeid(this) == typeid(that)) {
return this->equals(reinterpret_cast<Number&> (that));
} else {
return false;
}
}
bool Number::equals(Number &that) {
return this->value == that.value;
}
How can I fix this?
First, lets correct the interface:
class IExpression {
public:
virtual ~IExpression() {}
virtual bool hasVar()const=0 ; //does not modify
virtual double eval(double)=0 ;
virtual string getStr()const=0 ; //does not modify
virtual string getSmart()const=0 ; //does not modify
virtual bool equals(IExpression const&)const=0 ;//does not
modify
virtual IExpression simplify()=0 ;
virtual IExpression derivative()=0 ;
//convienence operator
bool operator==(IExpression const&r)const{
return equals(r);
}
};
And modify the Number class accordingly. Now lets fix the equal
function.
First note that Number::equal is defined twice (illegal) so we need to
define only one.
Second, note that the implementation using the typeid's causes
infinite recursion.
Third, "this" is a pointer type, specifically Number const *. you are
comparing to a reference type. The condition will never be true.
Fourth, class Number virtually inherits from IExpression. This is fine
(and IHMO preferred in this case), but note that when using virtual
inheritance you need to also use dynamic_cast, and not
reinterpret_cast.
Lets combine all this together to come up with something useful:
bool Number::equals(IExpression const&that)const {
if (Number const* p=dynamic_cast<Number const*> (&that) ) {
return value == p->value;
}
return false;
}
Now, the problem is that operator== on a double is rarely what you
want. You need a tolerance of some sort. i.e.
return fabs(value - p->value)<0.001;
or whateever is appropriate for your app
Lance