Jump to content

Virtual Method Problems

- - - - -

  • Please log in to reply
3 replies to this topic

#1
chili5

chili5

    Writes binary right handed and hex left handed

  • Members
  • PipPipPipPipPipPipPipPipPip
  • 7,247 posts
  • Programming Language:Java, C#, PHP
  • Learning:C, C++, C#, PHP, Transact-SQL, Assembly, Scheme
I'm doing a postfix calculator using C++ objects and running into a problem with object inheritance and virtual methods.

I have defined two classes:

class Expression {
    public:
             virtual int evaluate() = 0;
             virtual void print(std::ostream&) = 0;
};

class UnaryExpression : public Expression {
       public:
                     int evaluate();
                     void print(std::ostream&);
};

In Expression.cc my eval function is written to simply return 0. It has to be defined to something or it won't compile. It won't matter since this class will never be initialized directly.

The UnaryExpression has other stuff in but mostly it's a class that supports two operations negation and absolute value.

So in my file UnaryExpression.cc I defind evaluate like this:

int evaluate() {
         if (oper == "NEG") return -operand;
         if (operand < 0) return -operand;
         return operand;
}

My main function uses a stack which holds Expression objects (could be UnaryExpressions also). After the loop executes it will have one object on the stack which represents the final expression.

So if my expression was 5 NEG I will have a UnaryExpression(5, "NEG") on the stack which a call to evalulate will produce -5.

So my code is this:

Expression answer = s.top();
s.pop();

cout << answer.evalulate() << "\n";

The output is always 0 though and I can't figure out why... I defined the evalulate method in my UnaryExpression class and s.top() produces a UnaryExpression so it should call the UnaryExpression eval method but it's actually calling the method in the Expression class?

#2
WingedPanther

WingedPanther

    A spammer's worst nightmare

  • Moderators
  • 16,831 posts
  • Location:Upstate, South Carolina
  • Programming Language:C, C++, PL/SQL, Delphi/Object Pascal, Pascal, Transact-SQL, Others
  • Learning:Java, C#, PHP, JavaScript, Lisp, Fortran, Haskell, Others
Can you post the complete code needed to reproduce the problem? There's really no telling, right now.
Programming is a branch of mathematics.
My CodeCall Blog | My Personal Blog

#3
chili5

chili5

    Writes binary right handed and hex left handed

  • Members
  • PipPipPipPipPipPipPipPipPip
  • 7,247 posts
  • Programming Language:Java, C#, PHP
  • Learning:C, C++, C#, PHP, Transact-SQL, Assembly, Scheme
Main:

#include <iostream>
#include "Expression.h"
#include "NumberExpression.h"
#include "UnaryExpression.h"
#include <stack>
#include <sstream>

using namespace std;

int main()
{
    stack<Expression> s;
    string word = "";

    while (!cin.eof()) {
        cin >> word;

        if (word == "NEG" || word == "ABS") {
            // pop one Expression off the stack
            // evaluate the expression we popped off
            // push a new UnaryExpression onto the stack
            Expression x = s.top();
            s.pop();
            UnaryExpression newItem(x.evaluate(), word);
            s.push(newItem);
        }  else {
            // must be a number
            // create a new NumberExpression with this number and push it onto the stack
            stringstream ss(word);
            int num = -1;

            ss >> num;

            NumberExpression newItem(num);
            s.push(newItem);
        }
    }

    Expression answer = s.top();
    s.pop();

    cout << answer.evaluate() << "\n";

    // pop Expression off the stack
    // Evaluate it and print out the expression in infix as well as the value

    return 0;
}

Expression.h

#ifndef EXPRESSION_H_INCLUDED
#define EXPRESSION_H_INCLUDED
#include <iostream>

class Expression {
    public:
        Expression();
        ~Expression();

        virtual int evaluate();
        virtual void prettyprint(std::ostream&);
        int getFirstOperand() const;
        std::string getExpression();

    protected:
        int firstOperand;
        std::string expr;
};


#endif // EXPRESSION_H_INCLUDED

Expression.cc:

#include "Expression.h"

Expression::Expression() {
    firstOperand = 0;
    expr = "";
}

Expression::~Expression() {

}

int Expression::getFirstOperand() const {
    return firstOperand;
}

std::string Expression::getExpression() {
    return expr;
}

 int Expression::evaluate() {
    return 0;
 }

 void Expression::prettyprint(std::ostream& out) {

 }

UnaryExpression.h:

#ifndef UNARYEXPRESSION_H_INCLUDED
#define UNARYEXPRESSION_H_INCLUDED
#include <string>
#include <iostream>
#include "Expression.h"

class UnaryExpression : public Expression {
 private:
        std::string oper;
    public:
        UnaryExpression(int operand, std::string Operator);
        ~UnaryExpression();
        std::string getOperator() const;
        int evaluate();
        void prettyprint(std::ostream&);
};

#endif // UNARYEXPRESSION_H_INCLUDED

UnaryExpression.cc:

#include "UnaryExpression.h"
#include "Expression.h"
#include <string>


UnaryExpression::UnaryExpression(int operand, std::string Operator) : Expression() {
    firstOperand = operand;
    oper = Operator;
}

UnaryExpression::~UnaryExpression() {

}

std::string UnaryExpression::getOperator() const {
    return oper;
}

int UnaryExpression::evaluate() {
    int firstOperand = getFirstOperand();

    if (oper == "NEG") {
        return -1 * firstOperand;
    } else if (oper == "ABS") {
        if (firstOperand < 0) {
            return -1 * firstOperand;
        } else {
            return firstOperand;
        }
    }

    return 0; // shouldn't ever happen
}

void UnaryExpression::prettyprint(std::ostream& out) {
    if (oper == "NEG") {
        out << "-" << evaluate();
    } else if (oper == "ABS") {
        out << "|" << evaluate() << "|";
    }
}



NumberExpression.h:

#ifndef NUMBEREXPRESSION_H_INCLUDED
#define NUMBEREXPRESSION_H_INCLUDED
#include "Expression.h"
#include "NumberExpression.h"
#include <iostream>

class NumberExpression : public Expression {
    public:
        NumberExpression(int operand);
        ~NumberExpression();

        int evaluate();
        void prettyprint(std::ostream&);
};


#endif // NUMBEREXPRESSION_H_INCLUDED

NumberExpression.cc:

#include "NumberExpression.h"
#include "Expression.h"
#include <iostream>

NumberExpression::NumberExpression(int operand) : Expression() {
    firstOperand = operand;
}

NumberExpression::~NumberExpression() {

}

int NumberExpression::evaluate() {
    return firstOperand;
}

void NumberExpression::prettyprint(std::ostream& out) {

}


I think the problem is when I pop something off the stack that is a UnaryExpression and assign to an Expression object but that shouldn't be a problem since a UnaryExpression is an Expression. That's just a guess I'm not really sure what is happening. I find inheritance in C++ a little strange...

#4
Flying Dutchman

Flying Dutchman

    Programming God

  • Members
  • PipPipPipPipPipPipPip
  • 889 posts
  • Location:::1
This will only work with pointers.
Expression* a = new Expression;
Expression* b = new UnaryExpression;

a->evaluate(); // calls Expression::evaluate()
b->evaluate(); // calls UnaryExpression::evaluate()

A conclusion is where you got tired of thinking.
#define class struct    // All is public.




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users