Рекурсия вызваная из базового класса

363
27 января 2017, 06:38

Все мы знаем обычную рекурсию, например:

функция имя(){
    условие_завершения;
    имя();
}

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

Встретил вот такой код:

class SimpleDelegate : public QStyledItemDelegate {
public:
    void paint(QPainter*                   pPainter,
               const QStyleOptionViewItem& option,
               const QModelIndex&          index
              ) const
......
условие_выхода
......
    {
        QStyledItemDelegate::paint(pPainter, option, index); // рекурсия ?
    }
};

Вроде бы тоже рекурсия но как она работает? То ли копия базового объекта создается то ли просто метод дублируется для текущего объекта, то ли.. , в общем не понятно.

Answer 1

В данном определении функции-члена класса рекурсии нет

class SimpleDelegate : public QStyledItemDelegate {
public:
    void paint(QPainter*                   pPainter,
               const QStyleOptionViewItem& option,
               const QModelIndex&          index
              ) const
......
условие_выхода
......
    {
        QStyledItemDelegate::paint(pPainter, option, index); // рекурсия ?
    }
};

Имеются две различные функции. Одна функция - это SimpleDelegate::paint , другая функция - это QStyledItemDelegate::paint.

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

Рассмотрите данную демонстрационную программу

#include <iostream>
#include <string>
int main()
{
    struct A
    {
        void f(const char *) const { std::cout << "Hello"; }
        void f(char) const { std::cout << ' '; }
    };
    struct B : A
    {
        void f(const std::string &s ) const
        { 
            A::f(nullptr);
            A::f(' ');
            std::cout << s << std::endl;
        }
    };
    B().f(std::string("perfect"));
    return 0;
}

Ее вывод на консоль

Hello perfect

Здесь функция, объявленная в производном классе B скрывает одноименные функции, объявленные в базовом классе A. Поэтому чтобы обратиться к этим функциям базового класса в области определения производного класса, следует использовать квалифицированные имена функций базового класса.

Другой альтернативный подход при условии, что нет неоднозначности в перегрузке функций, это использовать using объявления в производном классе. Например,

struct B : A
{
    using A::f;
    void f(const std::string &s ) const
    { 
        f(nullptr);
        f(' ');
        std::cout << s << std::endl;
    }
};

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

Answer 2

QStyledItemDelegate::paint(pPainter, option, index); вызовет метод paint у класса QStyledItemDelegate, который является базовым, относительно SimpleDelegate. Это не является рекурсивным вызовом.

Понятно что эта функция будет существовать в памяти в нескольких экземплярах

у функций нет экземпляров.

READ ALSO
Размер массива string

Размер массива string

Есть массив типа string, в который может быть записано как 1, так и 200 значений

347
Получение директории из argv

Получение директории из argv

В argv[0] находится полный путь до до исполняемого файла, а как получить директорию, в которой находится файл?

364
Преобразование огромных чисел

Преобразование огромных чисел

Преобразую значения из string в long long

426