Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Переопределение виртуальной функции


Автор: шарлотта 9.5.2017, 01:05
Здравствуйте!
Требуется реализовать виртуальную функцию сложения в классе Array, переопределив ее в производном классе Fraction
Код

Array Array::operator +(const Array &arr) {
    Array res(*this);
    for (int i = 0; i < size; i++) {
        res.elems[i] += arr.elems[i];
    }
    return res;
}

Не могу понять, как это сделать. Ведь если написать так, то это будет перегрузка, а не переопределение виртуального метода.
Код

Fraction Fraction::operator +(const Fraction &num) {
    Fraction res(*this);
    for (int i = 0; i < size_integer; i++) {
        res.integer[i] += num.integer[i];
    }
    for (int i = 0; i < size_fract; i++) {
        res.fract[i] += num.fract[i];
    }
    return res;
}

Буду очень благодарна за помощь!

Автор: vpf 9.5.2017, 04:39
виртуальный метод не должен иметь тела в классе Array, только объявление.
Поэтому в классе Array вы даете только объявление функции
А в классе Fraction помещаете ее тело, то есть то, что вы дали в первом блоке кода.



Автор: tzirechnoy 9.5.2017, 10:26
Цитата
виртуальный метод не должен иметь тела в классе Array, только объявление.


Нет, это Вы с pure virtual перепутали, да и то в довольно старом понимании.

Цитата
то это будет перегрузка, а не переопределение виртуального метода.


Очень сложно понимать русскую терминологию, которой я дажэ не знаю где искать определения, но если перегрузка -- это overload, а переопределение -- это override, то 
Во-первых это всегда будет overload of an operator +, то есть без перегрузки тут никак не обойдётся.
Во-вторых, чтобы что-то override надо чтобы тот, кого override и тот, кто override находились в базовом и унаследованном классе. Собственно, для того, чтобы это наывалось override это почти единственное требование -- ну, кроме совпадения имени.
В-третьих, чтобы override был virtual -- нужно, чтобы в базовом классе этот оператор был объявлен virtual, а во-вторых -- чтобы сигнатуры функцый достаточно совпадали (допускается смена параметров-ссылок и указателей на ссылки на ковариантные классы).

Автор: шарлотта 9.5.2017, 12:15
В базовом и производном находятся, virtual объявлен. Проблема возникает как раз с сигнатурой функции. Не очень понимаю, как поменять типы переданных параметров и возвращаемого значения.

Попыталась сделать так, чтобы принимал указатели.
Код

Array& Array::operator +(Array *arr) {
    Array* res(this);
    for (int i = 0; i < size; i++) {
        (*res).elems[i] += (*arr).elems[i];
    }
    return *res;
}

Изменяет вызвавший объект. Буду очень благодарна за помощь!

Автор: tzirechnoy 10.5.2017, 02:15
1) Вообще, примерно всем любопытствующим было бы сильно проще, если бы Вы приводили минимальный компилирующийся пример. Одновременно мы могли бы его сами запустить, и нам не пришлось бы догадываться что у вас там за декларацыи, не забыт ли где virtual и пр.
2) Первый мой ответ был так сделать в динамической памяти, new(Array), но этот ответ очевидно дурацкий, поскольку память утекать будет.

А, собственно... А куда это всё из этого виртуального оператора присваиваться будет? Просто если это будет присваиваться всегда Array (включая ссылки на Array), то оба оператора и должны возвращать Array, а не Fraction. А если это будет присваиваться указателю на Array, то можно возвращать указатели на Array/Fraction, смело размещая их в динамической памяти, и рассчитывая что пользователь потом их удалит.

Собственно, дайте более полную задачу, да.

Автор: awesome 10.5.2017, 13:15
Цитата(шарлотта @ 9.5.2017,  01:05)
Здравствуйте!
Требуется реализовать виртуальную функцию сложения в классе Array, переопределив ее в производном классе Fraction
Код

Array Array::operator +(const Array &arr) {
    Array res(*this);
    for (int i = 0; i < size; i++) {
        res.elems[i] += arr.elems[i];
    }
    return res;
}

Не могу понять, как это сделать. Ведь если написать так, то это будет перегрузка, а не переопределение виртуального метода.
Код

Fraction Fraction::operator +(const Fraction &num) {
    Fraction res(*this);
    for (int i = 0; i < size_integer; i++) {
        res.integer[i] += num.integer[i];
    }
    for (int i = 0; i < size_fract; i++) {
        res.fract[i] += num.fract[i];
    }
    return res;
}

Буду очень благодарна за помощь!

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

Автор: volatile 10.5.2017, 15:08
Цитата(шарлотта @  9.5.2017,  01:05 Найти цитируемый пост)
Требуется реализовать виртуальную функцию сложения 

Здесь не сказано реализовать оператор сложения, а всего лишь функцию.
возможно имелось в виду что-то типа:
Код

void Array::add (const Array &arr);
в этом случае реализация банальна

Eсли же вам реально нужно именно оператор+ в классическом смысле, то вы привели недостаточно инфорамации, как уже здесь вам намекали

Автор: шарлотта 10.5.2017, 18:14
Разобралась. Большое спасибо!

Автор: sam992 25.5.2017, 16:19
Привет ребят!
Спасибо за ответы! Они и мне помогли! smile 

http://popupmaker.com/

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)