Как я могу перегрузить оператор для абстрактного класса? - PullRequest
2 голосов
/ 11 июля 2019

Я относительно новичок в C ++, и мой профессор не вдавался в подробности перегрузки операторов, как мне хотелось бы, когда я посещал его урок. Я пытаюсь реализовать способ сравнения объектов (используя> или <), которые все наследуют абстрактный класс, но у меня возникают проблемы с синтаксисом / логикой. </p>

Я пытался сделать его членом родительского класса, но я не мог понять, как вызывать чисто виртуальную функцию из базового класса. Затем я попытался использовать шаблоны, но это только вызывает у меня головную боль (мой профессор не слишком углубился в них).

Я знаю, что я полностью потерпел неудачу в функции оператора (и любая помощь с правильным синтаксисом была бы признательна).

#include <iostream>

enum cType { point, maxima, inflection };

class CONSTRAINT {
public:
    //coordinates
    int x, y;
    //gets what type of constraint the object is
    virtual cType getType() = 0; //pure virtual
    //I'm sure this syntax is horrendous and completely wrong.
    //I was just trying to emulate what I found online :(
    bool operator > (const CONSTRAINT &rhs) { 
            //If the constraints have the same type, compare by their x-value
        if (getType() == rhs.getType())
            return (x > rhs.x);
            //Otherwise, it should be point > maxima > inflection
        else
            return (getType() > rhs.getType());
    }
};
class POINT : public CONSTRAINT {
public:
    virtual cType getType() { return point; }
};
class MAXIMA : public CONSTRAINT {
public:
    virtual cType getType() { return maxima; }
};
//I have another inflection class that follows the pattern

int main() {
    POINT point1, point2;
    point1.x = 3;
    point2.x = 5;
    MAXIMA maxima;
    maxima.x = 4;
    std::cout << (point1 > point2);
    std::cout << (point2 > point1);
    std::cout << (maxima > point2);
    std::cout << (point1 > maxima );
    return 0;
}

Я бы ожидал: 0110 если программа скомпилируется.

Вместо этого я получаю следующие ошибки:

"объект имеет спецификаторы типа, которые не совместимы с функцией-членом" CONSTRAINT :: getType ""

"'cType CONSTRAINT :: getType (void)': невозможно преобразовать этот указатель из 'const CONSTRAINT' в 'CONSTRAINT &' '

Спасибо.

1 Ответ

3 голосов
/ 11 июля 2019

In

bool operator > (const CONSTRAINT &rhs)

rhs равно const.Это не может быть изменено внутри этого метода.Но ...

virtual cType getType() = 0; //pure virtual

Это не const метод.Это означает, что метод может изменить rhs, поэтому компилятор отказывается разрешить его вызов.

Решение: объявите метод const

virtual cType getType() const = 0; //pure virtual

Теперь компилятору обещают, чтовызов функции не позволит изменить rhs.Компилятор также принудительно выполнит это и откажется компилировать программу, если реализация getType попытается изменить объект, для которого она вызывается.

Примечания:

Как только метод объявлен как virtual, все переопределения также будут virtual.

Ключевое слово override будет перехватывать ошибки, если метод должен переопределить, но не из-за несоответствия.Добавление const к методу базового класса, но не к методу производного класса, является хорошим примером того, где это полезно.

Поскольку этот код использует преимущества полиморфизма во время выполнения, вам может потребоваться виртуальныйдеструктор в базовом классе, чтобы гарантировать, что правильные классы уничтожены, если вы однажды захотите delete производного класса через указатель на базовый класс.

Завершение всего этого:

#include <iostream>

enum cType { point, maxima, inflection };

class CONSTRAINT {
public:
    //coordinates
    int x, y;

    virtual ~CONSTRAINT() = default;
//  ^ added

    //gets what type of constraint the object is
    virtual cType getType() const = 0; //pure virtual
//                          ^ added
    //I'm sure this syntax is horrendous and completely wrong.
    //I was just trying to emulate what I found online :(
    bool operator > (const CONSTRAINT &rhs) {
            //If the constraints have the same type, compare by their x-value
        if (getType() == rhs.getType())
            return (x > rhs.x);
            //Otherwise, it should be point > maxima > inflection
        else
            return (getType() > rhs.getType());
    }
};
class POINT : public CONSTRAINT {
public:
    cType getType() const     override { return point; }
//                  ^ added   ^ added
};
class MAXIMA : public CONSTRAINT {
public:
    cType getType() const     override { return maxima; }
//                  ^ added   ^ added
};
//I have another inflection class that follows the pattern

int main() {
    POINT point1, point2;
    point1.x = 3;
    point2.x = 5;
    MAXIMA maxima;
    maxima.x = 4;
    std::cout << std::boolalpha // < added. prints true and false instead of 1 and 0
              << (point1 > point2) << '\n'
              << (point2 > point1) << '\n'
              << (maxima > point2) << '\n'
              << (point1 > maxima);
    // took advantage of chaining and added newlines to the output for clarity
    return 0;
}

Заключительное примечание: Обычно рекомендуется, чтобы operator< был реализован как Свободная функция .Подробнее об этом и многом другом о перегрузке операторов см. Каковы основные правила и идиомы перегрузки операторов?

...