Различные статьи по Qt и c++

Замена устаревших API при переходе на Qt6: таблица соответствий старых и новых классов

При миграции с Qt5 на Qt6 значительная часть работы — это механическая замена устаревших классов и методов. Ниже приведена таблица наиболее частых соответствий, а также примеры кода «было/стало» для самых проблемных случаев.

Таблица соответствий API

Qt5 (устаревшее/удалённое)Qt6 (рекомендуемое)Комментарий
QRegExpQRegularExpressionQRegExp доступен через модуль Qt5Compat
QStringRefQStringViewПолная замена, более широкий функционал
QTextCodecQStringConverter / QStringEncoderДля перекодирования текста
qrand(), qsrand()QRandomGeneratorСовременный, потокобезопасный генератор
QDesktopWidgetQScreen (через QGuiApplication::screens())QDesktopWidget удалён
Qt::AA_EnableHighDpiScalingНе требуется — включено по умолчаниюHigh DPI всегда активен в Qt6
QApplication::desktop()QGuiApplication::primaryScreen()Получение размеров экрана
qt_qFindChildQObject::findChild<T>()Устаревшая внутренняя функция
QLinkedListstd::listКонтейнер удалён из Qt6
QVectorQList (объединён с QVector)QVector — теперь алиас QList
QQuickView::rootContext()->setContextPropertyто же, но проверять время инициализацииПоведение порядка инициализации изменилось
QtQuick.Controls 1.xQtQuick.Controls 2.xControls 1 удалён полностью
QOpenGLWidget напрямую для 3D-сценQt Quick 3D / RHI-абстракцияРекомендуется для новых проектов
QSignalMapperЛямбды в connect()Более идиоматичный подход в C++11+
qSort() / qStableSort()std::sort() / std::stable_sort()Используем STL-алгоритмы напрямую
QString::SplitBehavior::KeepEmptyPartsQt::SplitBehaviorFlags::KeepEmptyPartsИзменено пространство имён enum

Пример: замена QRegExp

// Qt5
#include <QRegExp>

bool isValidEmail(const QString &email) {
    QRegExp rx("^[\\w.+-]+@[\\w-]+\\.[a-zA-Z]{2,}$");
    return rx.exactMatch(email);
}
// Qt6
#include <QRegularExpression>

bool isValidEmail(const QString &email) {
    static const QRegularExpression rx(
        "^[\\w.+-]+@[\\w-]+\\.[a-zA-Z]{2,}$");
    QRegularExpressionMatch match = rx.match(email);
    return match.hasMatch() && match.capturedLength() == email.length();
}

Пример: замена qrand на QRandomGenerator

// Qt5
qsrand(QTime::currentTime().msec());
int value = qrand() % 100;
// Qt6
int value = QRandomGenerator::global()->bounded(100);

QRandomGenerator потокобезопасен и не требует ручной инициализации seed — это и проще, и безопаснее в многопоточном коде.

Пример: замена QSignalMapper на лямбды

// Qt5
QSignalMapper *mapper = new QSignalMapper(this);
connect(button1, &QPushButton::clicked, mapper, [=]{ mapper->map(button1); });
mapper->setMapping(button1, 1);
connect(mapper, &QSignalMapper::mappedInt, this, &MyClass::onButtonClicked);
// Qt6 — лямбда захватывает нужный идентификатор напрямую
connect(button1, &QPushButton::clicked, this, [this]{ onButtonClicked(1); });
connect(button2, &QPushButton::clicked, this, [this]{ onButtonClicked(2); });

Пример: получение информации об экране

// Qt5
QRect screenRect = QApplication::desktop()->screenGeometry();
// Qt6
QRect screenRect = QGuiApplication::primaryScreen()->geometry();

Использование модуля совместимости Qt5Compat

Если переписать всё сразу невозможно (например, в стороннем коде), можно временно подключить модуль совместимости:

find_package(Qt6 REQUIRED COMPONENTS Core5Compat)
target_link_libraries(MyApp PRIVATE Qt6::Core5Compat)
#include <QtCore5Compat/QRegExp> // временное решение, не для нового кода

Подводные камни

  • QVector и QList объединены, но семантика QVector (гарантия contiguous storage) сохранена для QList в Qt6 — это упрощает миграцию, но код, рассчитывающий на отдельные оптимизации QVector, может потребовать профилирования.
  • enum-классы стали строже типизированными — неявные приведения int → enum в местах вроде Qt::SplitBehavior теперь требуют явного указания пространства имён.
  • QStringRef и QStringView не идентичны по API — у QStringView нет некоторых методов вроде toString() без копирования, проверяйте семантику владения данными.
  • Не удаляйте Qt5Compat сразу при миграции крупного проекта — используйте его как промежуточный шаг, переписывая код постепенно, модуль за модулем.

================================================================================