|
-
October 12th, 2009, 04:28 AM
#1
Passing objects to data structures
I have a problem with design that I need some help. I have classes as shown below, my problem is on COperator: oOperation,
explained in the comment. please help me through this. thank you.
Code:
CElement : public CObject
{
}
CNumber : public CElement
{
friend CNumber operator+(const CNumber& x, const CNumber& y);
{
CNumber result;
result.m_nNumber = x.m_nNumber + y.m_nNumber;
return result;
}
public:
CNumber& operator=(const CNumber& x);
{
if(this == &x)
return;
this->m_nNumber = x.m_nNumber;
return *this;
}
private:
int m_nNumber;
}
COperator : public CElement
{
public:
enum OP_TYPE {ET_ADD=0,ET_SUB,ET_MULTIPLY,ET_DIVIDE};
CElement* doOperation(CElement* op1,CElement* op2)
{
//here is the problem, when the result type is of CElement*,
//then returning this object would be not correct,
//becoz im expection a pointer to CNumber,
//or soon i'm adding another class called CFraction, so how do i do this?
//should I get the type of op1 and op2 then create a new object of that Type?
//if i do that, then how about if i'm doing the operation on CFraction class??
CElement* result;
switch(m_operator)
{
case ET_ADD:
result = op1 + op2;
case ET_SUB:
result = op1 - op2;
case ET_MULTIPLY:
result = op1 * op2;
case ET_DIVIDE:
result = op1 / op2;
};
}
private:
OP_TYPE m_operator;
}
CMathExpression : public CArray<CElement*,CElement*>
{
//this class would construct the math expression
//example,
this->AddTail(new CNumber(10));
this->AddTail(new COperator(ET_ADD));
this->AddTail(new CNumber(10));
}
CAlgorithm
{
public:
int evaluatePostfix()
{
CList<CElement*,CElement*> objTemp;
//convert "m_objExpr" to postfix and store in "objTemp"
//now evaluate the postfix expr and get the result
Stack s;// stack is a derived CList implimentation
POSITION pos = objTemp.GetHeadPosition();
while(pos)
{
switch(objTemp.GetType())//getType function is virtual common to all derived class from CElement
{
case ET_ELEMET:
case ET_NUMBER:
case ET_FRACTION:
s.push(objTemp.GetAt(i))
break;
case ET_OPERATOR:
CElement* operand2 = s.getTop();
s.pop();
CElement* operand1 = s.getTop();
s.pop();
CElement* result = ((COperaotr*)objTemp.GetAt(i))->doOperation(operand1,operand2);
s.push(result);
break;
};
}
//get and display the result which is at the top of the Stack
s.getTop()->toString(); //toString function is virtual common to all derived class from CElement
}
private:
CMathExpression m_objExpr; //this is an array of elements in "infix"
}
somewhereinafarfarawayclass::calculate()
{
CAlgorithm algo;
//... here all work done creating the expression
int nResult = algo. evaluatePostfix();
}
Last edited by Max Payne; October 12th, 2009 at 04:37 AM.
Come Join This Poll Where are we from? (Ultimate)
Knowing is not enough; we must apply. Willing is not enough; we must do. - Johann Wolfgang
An idle brain is the devil's workshop. - unknown
-
October 12th, 2009, 04:43 AM
#2
Re: Passing objects to data structures
another problem im confused is about the List or Stack data structures, since I create the Stack with CElement* type, and these element is created in the MathExpression class with "new", thus allocating memory for those element, the when I push the pointer into the stack, does it create or use more memory, so to avoid memory leak should I use "delete" those object after finished using the stack??
Come Join This Poll Where are we from? (Ultimate)
Knowing is not enough; we must apply. Willing is not enough; we must do. - Johann Wolfgang
An idle brain is the devil's workshop. - unknown
-
October 12th, 2009, 05:14 AM
#3
Re: Passing objects to data structures
 Originally Posted by Max Payne
Code:
...
COperator : public CElement
{
public:
enum OP_TYPE {ET_ADD=0,ET_SUB,ET_MULTIPLY,ET_DIVIDE};
CElement* doOperation(CElement* op1,CElement* op2)
{
//here is the problem, when the result type is of CElement*,
//then returning this object would be not correct,
//becoz im expection a pointer to CNumber,
//or soon i'm adding another class called CFraction, so how do i do this?
//should I get the type of op1 and op2 then create a new object of that Type?
//if i do that, then how about if i'm doing the operation on CFraction class??
CElement* result;
switch(m_operator)
{
case ET_ADD:
result = op1 + op2;
case ET_SUB:
result = op1 - op2;
case ET_MULTIPLY:
result = op1 * op2;
case ET_DIVIDE:
result = op1 / op2;
};
}
private:
OP_TYPE m_operator;
}
1. You should rewrite your enum as:
Code:
enum OP_TYPE
{
ET_ADD=0,
ET_SUB,
ET_MULTIPLY,
ET_DIVIDE
};
Otherwise it is absolutely unreadable!
2. Do you really want to do these operations (ET_ADD / ET_SUB / ET_MULTIPLY / ET_DIVIDE) with pointers, not with the objects?
Victor Nijegorodov
-
October 12th, 2009, 05:32 AM
#4
Re: Passing objects to data structures
i'm sorry, since i don't have the code with me rite now, i just write what I remembered of my program, so there is misttake in the operation class, it should be like this:
Code:
CElement& doOperation(CElement& op1,CElement& op2)
{
//here is the problem, when the result type is of CElement,
//then returning this object would be not correct,
//becoz im expection a pointer to CNumber,
//or soon i'm adding another class called CFraction, so how do i do this?
//should I get the type of op1 and op2 then create a new object of that Type?
//if i do that, then how about if i'm doing the operation on CFraction class??
CElement result;
switch(m_operator)
{
case ET_ADD:
result = op1 + op2;
case ET_SUB:
result = op1 - op2;
case ET_MULTIPLY:
result = op1 * op2;
case ET_DIVIDE:
result = op1 / op2;
};
return result;
}
Come Join This Poll Where are we from? (Ultimate)
Knowing is not enough; we must apply. Willing is not enough; we must do. - Johann Wolfgang
An idle brain is the devil's workshop. - unknown
-
October 12th, 2009, 05:57 AM
#5
Re: Passing objects to data structures
 Originally Posted by Max Payne
i'm sorry, since i don't have the code with me rite now, i just write what I remembered of my program, so there is misttake in the operation class, it should be like this:
In this case wouldn't it better to wait until you'll have your actual code to discuss you problems?
Otherwise, we'd have to deal with non-compilable code like this one:
 Originally Posted by Max Payne
Code:
...
public:
CNumber& operator=(const CNumber& x);
{
if(this == &x)
return;
this->m_nNumber = x.m_nNumber;
return *this;
}
Victor Nijegorodov
-
October 13th, 2009, 09:58 PM
#6
Re: Passing objects to data structures
Ok, here is my actual code, so please help on the doOperation method, cause i'm casting the CElement to CNumber before doing the operation (+,-,* or /). And the result is a CNumber, I don't know how to make the result of CElement type, so that i don't have to do different implementation for other types like CFraction... thankyou...
Code:
//operator overload
CNumber operator+(const CNumber& lValue,const CNumber& rValue)
{
CNumber tmp;
tmp.m_nNumber = lValue.m_nNumber + rValue.m_nNumber;
return tmp;
}
CNumber operator-(const CNumber& lValue,const CNumber& rValue)
{
CNumber tmp;
tmp.m_nNumber = lValue.m_nNumber - rValue.m_nNumber;
return tmp;
}
CNumber operator*(const CNumber& lValue,const CNumber& rValue)
{
CNumber tmp;
tmp.m_nNumber = lValue.m_nNumber * rValue.m_nNumber;
return tmp;
}
CNumber operator/(const CNumber& lValue,const CNumber& rValue)
{
CNumber tmp;
tmp.m_nNumber = lValue.m_nNumber / rValue.m_nNumber;
return tmp;
}
const CNumber& CNumber::operator=(const CNumber& number)
{
if(this == &number)
return *this;
this->m_nNumber = number.m_nNumber;
return *this;
}
Code:
CNumber COperator::doOperation(CElement& operand1,CElement& operand2)
{
switch(m_Operator)
{
case OperatorType::ADD:
return ((CNumber&)operand1+(CNumber&)operand2);
case OperatorType::SUBTRACT:
return ((CNumber&)operand1) - ((CNumber&)operand2);
case OperatorType::MULTIPLY:
return ((CNumber&)operand1) * ((CNumber&)operand2);
case OperatorType::DIVIDE:
return ((CNumber&)operand1) / ((CNumber&)operand2);
};
}
Code:
CString CExpr::toPostfix()
{
CStack stack;
CList<CElement*,CElement*> m_objTmp; //temporary list of postfix
for(int i=0;i<m_objExpr.GetSize();i++)
{
switch(m_objExpr.GetAt(i)->getType())
{
case ElemType::ET_ELEMENT:
case ElemType::ET_NUMBER:
stack.push(m_objExpr.GetAt(i));
break;
case ElemType::ET_OPERATOR:
while(!stack.isEmpty() && (*(COperator*)m_objExpr.GetAt(i)<=*(COperator*)stack.getTop()))// && !CElement::isOperator(stack.getTop()->getType()))
{
m_objTmp.AddTail(stack.getTop());
stack.pop();
}
stack.push(m_objExpr.GetAt(i));
break;
case ElemType::ET_EXPR:
break;
};
}
while(!stack.isEmpty())
{
m_objTmp.AddTail(stack.getTop());
stack.pop();
}
//just in case make sure stack empty
//TODO
//stack.show();
//now lets evaluate the postfix
CElement *tmpElem;
CNumber result;
POSITION pos= m_objTmp.GetHeadPosition();
while(pos)
{
tmpElem = m_objTmp.GetNext(pos);
if(CElement::isOperand(tmpElem->getType()))
{
stack.push(tmpElem);
}
else
{
CElement *operand2 = stack.getTop();
stack.pop();
CElement *operand1 = stack.getTop();
stack.pop();
result = (((COperator*)tmpElem)->doOperation(*operand1,*operand2));
stack.push(&result);
//DEBUG:stack.show();
}
}
//postfix string
CString strTmp=_T("");
pos= m_objTmp.GetHeadPosition();
while(pos)
{
CElement* elem = m_objTmp.GetNext(pos);
strTmp+=elem->toString();
}
//result
strTmp += _T(" = ") + stack.getTop()->toString();
return strTmp;
}
Come Join This Poll Where are we from? (Ultimate)
Knowing is not enough; we must apply. Willing is not enough; we must do. - Johann Wolfgang
An idle brain is the devil's workshop. - unknown
-
October 15th, 2009, 02:03 AM
#7
Re: Passing objects to data structures
CG is dead....
Come Join This Poll Where are we from? (Ultimate)
Knowing is not enough; we must apply. Willing is not enough; we must do. - Johann Wolfgang
An idle brain is the devil's workshop. - unknown
-
October 15th, 2009, 09:06 AM
#8
Re: Passing objects to data structures
Code:
CElement : public CObject
1) This code will not compile. You are either missing class or struct before CElement.
Take time to copy and paste your actual code from your editor -- do not type it into the message.
2) Why are you deriving from CObject? If you didn't, then you don't need that assignment operator you coded. There is absolutely no need for derivation from CObject, and by doing so, you were forced to code a copy constructor. Don't derive from classes that do not add functionality, only extra baggage and headaches.
3) There is already a std::stack class. There is no need for this CStack class.
Regards,
Paul McKenzie
Last edited by Paul McKenzie; October 15th, 2009 at 09:12 AM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|