I'm having a problem with this:
I'm writing an expression parser for a class project; I thought it would be a swell idea to have an abstract (binary) operator class which other classes implement. This is shown below.
Problems arise when I try to do something like this, however:
// should return an instance of the addition operator
Operator o = Operator::Create('+');
The error is this: "Abstract classes cannot be instatiated." I know what this means, but I never tried to do this; Create() calls the AdditionOperator constructor, as shown below.
In a vain effort to simply avoid my problems, I made the Operator class nonabstract, but with virtual functions that didn't do anything. However, when I debug and look at what is returned by Operator::Create(), the return object's function virtual function tables all point to the Operator functions instead of the derrived class!
Any help?
class Operator
{
public:
static Operator Create(char symbol);
virtual double Execute(double lh, double rh) const = 0;
virtual PRECEDENCE Precedence() const = 0;
virtual std::string ToString() const = 0;
bool operator<(const Operator& o) const
{
return (Precedence() < o.Precedence());
}
bool operator>(const Operator& o) const
{
return (Precedence() > o.Precedence());
}
};
Operator Operator::Create(char symbol)
{
switch(symbol)
{
case '(':
return ParenthesesOperator(false);
case ')':
return ParenthesesOperator(true);
case '^':
return PowerOperator();
case '*':
return MultiplicationOperator();
case '/':
return DivisionOperator();
case '+':
return AdditionOperator();
case '-':
return SubtractionOperator();
default:
throw "Error: unknown operator.";
}
}
class PowerOperator : public Operator
{
public:
double Execute(double lh, double rh) const
{
return std::pow(lh, rh);
}
PRECEDENCE Precedence() const
{
return PRECEDENCE_HIGH;
}
std::string ToString() const
{
return "^";
}
};
Operator Operator::Create(char symbol)
{
switch(symbol)
{
case '(':
return ParenthesesOperator(false);
case ')':
return ParenthesesOperator(true);
case '^':
return PowerOperator();
case '*':
return MultiplicationOperator();
case '/':
return DivisionOperator();
case '+':
return AdditionOperator();
case '-':
return SubtractionOperator();
default:
throw "Error: unknown operator.";
}
}
As far as I can see, you're essentially shredding whatever derived-object you return. Try returning a reference or pointer instead.
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.8
http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.20
That's what I thought. I guess I'll create an object factory that returns a pointer and deletes all the pointers when they go out of scope.