How to fix compiler error "class has no member named X"?

21,185

Solution 1

It's pretty clear, right? Expression doesn't have the method divide.

Expression *tmp;
Divide d;
tmp = &d;
tmp->divide(4, 2); //tmp is an Expression*

Also... why would you do this? What's wrong with:

Divide d;
d.divide(4,2);

Solution 2

Your problem is that you are calling divide on the variable called temp which is a pointer to an Expression here: tmp->divide(4, 2); You should call divide on your d variable.

Share:
21,185
Chris
Author by

Chris

Updated on July 05, 2022

Comments

  • Chris
    Chris almost 2 years

    I'm currently coding an expression evaluator and have run into an issue regarding polymorphism. My class hierarchy is as follows: Divide inherits from Operator which inherits from the base class Expression. When I instantiate an Object of type Divide with base class Expression and try to access the function divide(int, int) i get the following error:

    "Expression.cpp: In member function ‘int Expression::evaluate()’: Expression.cpp:37:6: error: ‘class Expression’ has no member named ‘divide’"

    Here is "Expression.h"

    #ifndef EXPRESSION_H
    #define EXPRESSION_H
    #include <string>
    using namespace std;
    class Operator;
    class Divide;
    class Expression 
    {
      protected:
        char **ana, *exp;
    
      public:
       Expression();
       ~Expression();
       Expression(char* ex);
       int evaluate();
       void tokenize();
    
        class EmptyException
        {
           public:
         EmptyException(string a){reason = a;};
         string getReason() const{return reason;};
           private:
         string reason;
        };
    
    };
    
    #endif
    

    And here is "Expression.cpp"

    #include "Expression.h"
    #include "Stack.h"
    #include "Queue.h"
    #include "Node.h"
    #include <iostream>
    #include <cstring>
    #include <stdio.h>
    #include <ctype.h>
    #include "Operator.h"
    #include "Divide.h"
    
    Expression::Expression()
    {
    
    } 
    
    Expression::~Expression()
    {
       delete [] exp;
    }
    
    Expression::Expression(char* ex)
    {
       exp = ex;
       //tokenize();
    
    }
    
    int Expression::evaluate()
    {
      Stack stack;
    
      Expression *tmp;
      Divide d;
      tmp = &d;
      tmp->divide(4, 2);
      stack.push(tmp);
       tmp = stack.pop();
    
     }
    
     void Expression::tokenize()
     {  
       int space = 0;
    
       for(int i  =0 ; i < strlen(exp); i++)
       {
         if(exp[i] == ' ')
         space++;
       } 
    
       char ** ana = new char*[space + 1];
       ana[0] = strtok(exp, " ");
    
       for(int i = 1 ; i < space + 1; i++)
       {        
       ana[i]= strtok (NULL, " ");
       }
    
      } 
    

    And now the "operator.h"

    #ifndef OPERATOR_H
    #define OPERATOR_H
    #include "Expression.h"
    
    using namespace std;
    
    class Operator : public Expression
    {
      protected:
        bool unary, binary;
      public:
        Operator();
        bool isUnary() const;
        bool isBinary() const;
    };
    
    #endif
    

    "Operator.cpp"

    #include "Operator.h"
    #include <string>
    #include <cmath>
    #include "Expression.h"
    
    Operator::Operator()
    {
    
    }
    
    bool Operator::isUnary() const 
    {
          if(unary)
        return true;
          else
        return false;
    
    }
    
    bool Operator::isBinary() const 
    {
          if(binary)
        return true;
          else
        return false; 
    }
    

    "Divide.h"

    #ifndef DIVIDE_H
    #define DIVIDE_H
    
    #include <string>
    #include "Operator.h"
    class Expression;
    using namespace std;
    
    
    class Divide : public Operator
    {
            private:
          char id;
        public:
            Divide();
            Divide(char);
            int divide(int a, int b);
            char identity() const;
    };
    
    #endif
    

    "Divide.cpp"

    #include "Divide.h"
    
    int Divide::divide(int a, int b)
    {
      return a/b;
    }
    
    Divide::Divide(char _id)
    {
     id = _id; 
    }
    
    char Divide::identity() const
    {
      return id;
    }
    

    and for in case the makefile

    main: Expression.o Equation.o Operator.o Divide.o Stack.o Queue.o main.o
       g++ -static main.o Equation.o Expression.o Operator.o Divide.o Stack.o Queue.o -o main
    
    main.o : main.cpp 
            g++ -c main.cpp 
    
    Equation.o : Equation.cpp Equation.h
        g++ -c Equation.cpp
    
    Expression.o : Expression.cpp Expression.h 
        g++ -c Expression.cpp 
    
    Operator.o : Operator.cpp Operator.h Expression.h 
        g++ -c Operator.cpp 
    
    Divide.o : Divide.cpp Divide.h Operator.h
        g++ -c Divide.cpp 
    
    Stack.o : Stack.cpp Stack.h Node.h
        g++ -c Stack.cpp
    
    Queue.o : Queue.cpp Queue.h Node.h
        g++ -c Queue.cpp
    

    I have left out all the other operators such as eg. Plus, minus etc because they are all identical to what Divide is and would just complicate this question even further.

  • Chris
    Chris over 11 years
    Well my stack takes an Expression* so that i dont end up using more than one stack to cater for multiple types, ie Divide, Add, Multiply, power etc. So when I parse my input equation and begin to push onto the stack, I want to be able to create a Divide or Add object that will inherit from Operator and Expression (base class).
  • Luchian Grigore
    Luchian Grigore over 11 years
    @Chris that still doesn't explain why you need the local object.
  • Chris
    Chris over 11 years
    I understand what your saying, but i dont want d to call divide, i want it to be polymorphic?
  • Luchian Grigore
    Luchian Grigore over 11 years
    @Chris you have no virtual methods in your code, how can anything be polymorphic?
  • Luchian Grigore
    Luchian Grigore over 11 years
    @Chris judging by your comments, it seems there's a deeper problem, which is why I recommend this - stackoverflow.com/questions/388242/… the question (as you intend it at least, not as posted) is too broad to be answered on SO.
  • Chris
    Chris over 11 years
    Ok, i see what you mean, but in this case divide doesn't need to be virtual, does it? What am I not understanding about the statement Expression *tmp = new Divide(); ? Is this not possible?
  • Luchian Grigore
    Luchian Grigore over 11 years
    @Chris it is, but tmp is still a pointer to an Expression...