Как исправить перегрузку приращения и оператора + и ошибку сегментации?

Я просмотрел несколько статей, которые кажутся похожими на мои проблемы, возникающие у меня при выполнении домашней работы для введения в C++, но я все еще не могу найти решение.

Я пытаюсь перегрузить оператор +, чтобы увеличить пассажировместимость на int n. Также перегрузка оператора ++ для увеличения пассажировместимости на 1.

Обратите внимание, что в моем классе происходит полиморфизм, у меня есть Ship (базовый), CruiseShip (производный).

Конструктор круизного корабля:

CruiseShip::CruiseShip(string name, string year, int passengers) : Ship(name, year)
{
    maxPassengers = passengers;
}

Перегрузки оператора:

CruiseShip& CruiseShip::operator+(int n) const
{
    maxPassengers += n;
    return *this;
}

CruiseShip& CruiseShip::operator++() // prefix
{
    ++maxPassengers;
    return *this;
}

CruiseShip CruiseShip::operator++(int) // postfix
{
    CruiseShip temp(*this);
    operator++();
    return temp;
}

Главный:

int main()
{

//Create objects, pointers
Ship *ships[3] = {new Ship("Titania", "2020"), new CruiseShip("Lusia", "2029", 200), new CargoShip("Luvinia", "2025", 500)};

//Print out ships
for(Ship *s : ships)
{
    s -> print();
    cout << endl;
}

//Reset a ships passenger, capacity
//I've tried testing each individually and all 3 still end up with segmentation errors
ships[1] = ships[1] + 5; //segmentation error related to this
ships[1]++; // segmentation error related to this
++ships[1]; // segmentation error related to this

//Print out ships
for(Ship *s : ships)
{
    s -> print();
    cout << endl;
}

//deallocate
return 0;
}

Насколько я могу судить, ваш operator+ не должен даже компилироваться. Разместите минимальный воспроизводимый пример.

melpomene 04.12.2018 02:24

Массив не содержит объектов, он содержит указатели. Итак, то, что вы делаете, - это арифметические операции с указателями, которые не связаны с вашими перегруженными операторами.

S.M. 04.12.2018 02:26

@ S.M. Итак, насколько я понимаю, я, по-видимому, выполняю эти операции с адресом, на который указывает указатель, а не с самим объектом? Если да, сможет ли это исправить разыменование?

Amai 04.12.2018 02:32

Попробуй сам.

S.M. 04.12.2018 02:34

Я попытался отрегулировать его, но, похоже, у меня все еще возникает ошибка. Хм :/

Amai 04.12.2018 02:43
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
73
1

Ответы 1

Чтобы добиться этого, используйте виртуальные функции. Но мы сталкиваемся с проблемой, что базовый класс не может вернуть объект производного класса. Итак, чтобы решить эту проблему, мы можем просто заставить класс Derived вместо этого возвращать базовый класс. Итак, вот пример кода:

class Ship
{
public:
    Ship(string name, string year)
    {
        this->name = name;
        this->year = year;
    }

    virtual Ship & operator + (int n)
    {
        return *this;
    }

    virtual Ship & operator ++()
    {
        return *this;
    }

    virtual Ship & operator ++ (int i)
    {
        return *this;
    }
public:

    string name;
    string year;
};

class CruiseShip : public Ship
{
public:
    virtual Ship& operator+(int n)
    {
        maxPassengers += n;
        return *this;
    }

    virtual Ship & operator++() // prefix
    {
        ++maxPassengers;
        return *this;
    }

    virtual Ship & operator++(int) // postfix
    {
        CruiseShip temp(*this);
        operator++();
        return temp;
    }


    CruiseShip(string name, string year, int passengers) : Ship(name, year)
    {
        maxPassengers = passengers;
    }

    int maxPassengers;

};

Создание виртуальной функции как в базовом, так и в производном классах позволяет иметь определение независимо от типа корабля И по-прежнему позволяет нам определять виртуальную функцию по-разному в производном классе.

Обратите внимание, что перегруженные операторы CruiseShip возвращают Ships, а не CruiseShips. Это удовлетворяет требованию иметь тот же тип возвращаемого значения виртуальной функции.

Затем в main единственные изменения, которые вам нужно будет сделать, - это разыменовать указатель и поместить этот разыменованный указатель в круглые скобки следующим образом: (*Ship[1])++

operator+ нужен только один аргумент, если это функция-член, каковым кажется. Тем не менее, operator+ почти всегда не должен быть членом, поэтому предоставление его в качестве функции-члена является недостатком дизайна (и он должен возвращать новое значение, а не ссылку; operator+ в том виде, в каком он написан, подходит для operator+=, а не operator+).
ShadowRanger 04.12.2018 03:25

Мой класс корабля не включает его, в основном потому, что я не уверен, как я это сделаю, я подумал об использовании виртуального, но это означало бы, что заголовок функции должен быть таким же (что не сработает b / c возврата тип). Честно говоря, я не уверен, как разыменовать свои указатели, я пробовал несколько разных способов, и все они все еще заканчиваются ошибками сегментации.

Amai 04.12.2018 03:30

Если вы хотите сделать это так, как вы это делаете, вам придется либо объявить свой CruiseShip как CruiseShip, либо сделать виртуальных перегруженных операторов. Это из-за типа, который вы используете. Если вы выбираете виртуальный маршрут, вы правы, Корабль должен возвращать тот же тип. Чтобы решить эту проблему, необходимо, чтобы все конкретные классы перегружали виртуальную функцию ИЛИ возвращали сам Ship, ничего не делая с ним. Но он должен возвращать тот же тип.

cwbusacker 04.12.2018 03:40

Если я должен вернуть CruiseShip для моего оператора ++, но CruiseShip не входит в сферу ответственности Корабля. Я не понимаю, как будет работать виртуальная функция, потому что в классе корабля вы не сможете записать ее как virtual CruiseShip operator++(int). В классе CruiseShip это необходимо.

Amai 04.12.2018 03:51

Ах. Тогда вы правы, вероятно, это не должно быть виртуальным. Я думаю, что лучшим способом было бы объявить 3 разных указателя для кораблей. Таким образом, они не относятся к типу Ship. Я продемонстрировал это, и это сработало. Я выложу свое решение

cwbusacker 04.12.2018 04:10

Да ... проблема в том, что домашнее задание велело нам создать массив указателей кораблей, иначе я бы точно не сделал это таким образом.

Amai 04.12.2018 04:24

@Amai Я обновил ответ и подтвердил, что он работает.

cwbusacker 04.12.2018 19:17

Другие вопросы по теме