This thread may be too much for a newbie without additional context.
I think that the design questions being discussed are extremely important.
I've provided some source that may give a newbie enough context to follow along without necessarily understanding the finer points.
The small details, such markup as names and layout, are optional of course; it is the concepts shown that are center to the discussion.
Soma
Code:
// The preferred approach whenever possible.
double Calculator::run()
{
// ...
switch(lOperation)
{
// ...
case Add:
{
// ...
// We are going to perform the addition operation.
// The addition operation is a binary operation.
// We know we need two values in the stack.
// We know that the operation can't fail if the precondition is valid.
// We have a way to get the size of the stack. (Precondition.)
// ...
if(2 <= lValues.size())
{
double lLHS(lValues.top());
lValues.pop();
double lRHS(lValues.top());
lValues.pop();
// ...
}
// ...
}
// ...
}
// ...
}
Code:
// This is not as clean as the above, but it is usually possible.
double Calculator::run()
{
// ...
switch(lOperation)
{
// ...
case Add:
{
// ...
// We are going to perform the addition operation.
// The addition operation is a binary operation.
// We know we need two values in the stack.
// We know that the operation can't fail if the precondition is valid.
// We have no way of knowing how many items are in the stack.
// We can check if the stack is empty. (Precondition.)
// ...
double lLHS(0.0);
double lRHS(0.0);
if(!lValues.empty())
{
lLHS = lValues.top();
lValues.pop();
if(!lValues.empty())
{
lRHS = lValues.top();
lValues.pop();
// ...
}
else
{
// ...
// We have to deal with the error in some fashion.
// ...
}
}
// ...
// ...
}
// ...
}
// ...
}
Code:
// This is a totally unacceptable approach which no one is advocating and included only for completeness.
double Calculator::run()
{
// ...
switch(lOperation)
{
// ...
case Add:
{
// ...
// We are going to perform the addition operation.
// The addition operation is a binary operation.
// We know we need two values in the stack.
// We know that the operation can't fail if the precondition is valid.
// We have no way of knowing how many items are in the stack.
// We will not check if the stack is empty for this example. (Precondition.)
// We know that the operation does nothing in the face of a precondition violation.
// We know that the operation does not do any notification in the face of a precondition violation.
// ...
double lLHS(0.0);
double lRHS(0.0);
lLHS = lValues.top();
lValues.pop();
lRHS = lValues.top();
lValues.pop();
// ...
// We have no way of knowing if an error occurred.
// ...
}
// ...
}
// ...
}
Code:
// The approach centered around returning a boolean value.
double Calculator::run()
{
// ...
switch(lOperation)
{
// ...
case Add:
{
// ...
// We are going to perform the addition operation.
// The addition operation is a binary operation.
// We know we need two values in the stack.
// We know that the operation can't fail if the precondition is valid.
// We have no way of knowing how many items are in the stack.
// We will not check if the stack is empty for this example. (Precondition.)
// We know that the operation does nothing in the face of a precondition violation.
// We know that the operation does notification in the face of a precondition violation.
// ...
double lLHS(0.0);
double lRHS(0.0);
lLHS = lValues.top();
if(lValues.pop())
{
lRHS = lValues.top();
if(lValues.pop())
{
// ...
}
else
{
// ...
// We have to deal with the error in some fashion.
// ...
}
}
}
// ...
}
// ...
}
Code:
// The approach centered around raising an exception.
double Calculator::run()
{
// ...
switch(lOperation)
{
// ...
case Add:
{
// ...
// We are going to perform the addition operation.
// The addition operation is a binary operation.
// We know we need two values in the stack.
// We know that the operation can't fail if the precondition is valid.
// We have no way of knowing how many items are in the stack.
// We will not check if the stack is empty for this example. (Precondition.)
// We know that the operation raises an exception in the face of a precondition violation.
// ...
double lLHS(lValues.top());
lValues.pop();
double lRHS(lValues.top()); // We know the `pop' operation was successful or we wouldn't have gotten to this point in code.
lValues.pop();
//
// We know the `pop' operation was successful or we wouldn't have gotten to this point in code.
// ...
}
// ...
}
// ...
}
// ...
void Calculator::apply
(
const char * fExpression
)
{
// ...
try
{
// ...
run();
// ...
}
catch(...)
{
// ...
// We have to handle the error in some fashion.
// ...
}
// ...
}
// ...