Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this class abstract?

I'm trying to create an implementation of a LinkedList that represents polynomials. The Linked list is going to be a list of "Term"s. A term is an implementation of Data (which is an abstract class with methods: compareTo() and toString()). The Polynomial class has a variable called head which I am trying to initialize as a Term. My compiler is saying that I "cannot declare member of abstract type: Term", but I did not think Term was abstract because it is an implementation of Data (the abstract class). If you guys could take a look at this and let me know of any huge red flags I'm missing, I would greatly appreciate it. Collection.h:

  class Data {
  public:
  virtual ~Data() {}

virtual int compareTo(Data * other) const = 0;

virtual string toString() const = 0;
};

class Term : public Data { 
public:
int coefficient;
string variable1;
int exponentX;
string variable2;
int exponentY;
Term * next;

Term(int coeff, string var1, int exp1, string var2, int exp2, Term * next) : 
    coefficient(coeff), 
    variable1(var1),
    exponentX(exp1),
    variable2(var2),
    exponentY(exp2),
    next(next) {};

string convertInt(int number) {
    stringstream ss;//create a stringstream
    ss << number;//add number to the stream
    return ss.str();//return a string with the contents of the stream
}

int compareTo(Term * term) {
    if(this->exponentX > term->exponentX) {
    return 1;
    }
    else if(this->exponentX < term->exponentX) {
    return -1;
    }
    else {
        if(this->exponentY > term->exponentY) {
        return 1;
        }
        else if(this->exponentY < term->exponentY) {
        return - 1;
        }
        else {
        return 0;
        }
    }
}
string toString() {
    stringstream s;
    int * current = &this->coefficient;
    if(*current == 1 || *current == -1) {
    }
    else if(coefficient != 0) {
    s << convertInt(coefficient);
    }
    else { return s.str(); }
    if(variable1 != "" && this->exponentX != 0) {
    s << variable1;
    s << convertInt(exponentX);
    }
    if(variable2 != "" && this->exponentY != 0) {
    s << variable2;
    s << convertInt(exponentY);
    }
return s.str();
}   
};

Also, here is implementation of LinkedList. There are some other methods in there, but they don't seem to be giving any issues.

LinkedList.cpp:

 class Polynomial : public LinkedList { 
public:
Term head;

Polynomial() {
this->head = NULL;
}

~Polynomial() {
Term * current = head;
    while (current != NULL) {
        Term * next = current->next;
        delete current;
        current = next;
    }
}

Thank you!


1 Answers

When you are overriding virtual methods, you have to match the function signatures precisely. The return type may vary in accordance with covariance rules, but the parameter types must be exactly the same.

In the base class Data function compareTo is declared as

virtual int compareTo(Data * other) const

In the derived class Term it is declared as

int compareTo(Term * term)

Firstly, the parameter type is different. Secondly, the const is missing.

This means that you wrote a completely unrelated function in the derived class. It does not override the base class's pure virtual function. Since the base pure virtual function remain non-overriden, class Term is still abstract.

In Term you have to declare your function precisely as

int compareTo(Data * other) const

I assume that you expect to use compareTo in Term only for Term-to-Term comparisons. But in this design you'll have to either receive Data as an argument and then cast it to Term, or use the double-dispatch technique.

P.S. On top of that you declare a Term object as a member head of your Polynomial class and then later use it as if it is a pointer

Term * current = head;

This makes no sense at all. If you want your head to be a pointer, declare it as a pointer. If you want it to be an object, then stop using it as a pointer. Either this or that.

like image 193
AnT Avatar answered Sep 23 '25 05:09

AnT