LINUX.ORG.RU

Почему не срабатывает static_cast в main.cpp, а в других местах срабатывает?

 , ,


0

5

Я в проекте использую расширенный от QGuiApplication класс, названный мною App, который отличается от QGuiApplication только одним дополнительным элементом:

class App : public QGuiApplication
{
public:
    App(int &argc, char **argv);

    Core core;
};

И у меня есть такой макрос:
#define APPCORE static_cast<App*>(qApp)->core

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

Однако, если я пытаюсь использовать макрос APPCORE в функции, которая просто лежит в main.cpp:
void criticalError(QString message)
{
 ...
    APPCORE.emitCriticalError(message);
 ...
}

то при компиляции возникает ошибка:
../src/main.cpp: In function ‘void criticalError(QString)’:
../src/main.h:21:39: error: invalid static_cast from type ‘QApplication*’ to type ‘App*’
 #define APPCORE static_cast<App*>(qApp)->core
                                       ^
../src/main.cpp:78:5: note: in expansion of macro ‘APPCORE’
     APPCORE.emitCriticalError(message);
     ^
Makefile:1998: recipe for target 'main.o' failed
make: *** [main.o] Error 1

Что-то я не пойму, почему приведение типов from ‘QApplication*’ to ‘App*’ работает во всей программе, но не работает именно в этом месте?

UPD Ссылка на минимальный пример: Почему не срабатывает static_cast в main.cpp, а в других местах срабатывает? (комментарий)

или : https://www.dropbox.com/s/6y53llhtcw38fh1/staticCastSample.rar?dl=0

★★★★★

Последнее исправление: Xintrea (всего исправлений: 4)

Ответ на: комментарий от Xintrea

Тьфу, не core, а аpp.h, прошу прощения. Или где App задекларирован? Должен быть выше criticalError.

Есть исходники на гитхабе?

ncuxer
()
Ответ на: комментарий от ncuxer

Естественно, и Core.h и App.h подключены.

Не, это закрытый проект.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от ncuxer

Щас демонстрационный пример сделаю..

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от MikeDM

Ну вне app.exec() максимум, что может быть, так это битый указатель.

Но приведение типов static_cast на этапе компиляции должно срабатывать везде.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Нужен пример, из обрывков кода сложно понять последовательность

jo_b1ack ★★★★★
()

Скорее всего у тебя обьявление макроса идёт раньше чем объявлен qApp

jo_b1ack ★★★★★
()
Ответ на: комментарий от DELIRIUM

Вот минимальный пример:

http://rgho.st/77LWnZhYQ

Он нормально собирается, причем в файле GlobalParameters.cpp есть строка:

APPCORE.emitCriticalError("Any message");

И она нормально компилируется.

Если же в файле main.cpp раскомментировать такую же строку 61:
// APPCORE.emitCriticalError(message);

То будет ошибка компиляции.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Попробуй отнаследоваться от QApplication а не от QGuiApplication. Ибо может не быть в этой точке инфы о том, что QApplication есть наследник QGuiApplication.

pon4ik ★★★★★
()

Емнип, qApp в разных хедерах Qt определяется по-разному, с разным типом. Проверь как он раскрывается у тебя в разных местах.

anonymous
()
Ответ на: комментарий от pon4ik

Попробуй отнаследоваться от QApplication а не от QGuiApplication.

Эээ, а как же тогда будут работать все графические части? У меня же не консольное приложение.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Вообще то QApplication есть наследник QGuiApplication. А в консольном приложении используется QCoreApplication, насколько я помню из своего опыта Qt 7летней давности :)

pon4ik ★★★★★
()
Ответ на: комментарий от KennyMinigun

Ну вот я добавил в main.cpp:

#include <type_traits>
...
qDebug() << "Is base of: " << std::is_base_of<std::remove_pointer_t<decltype(qApp)>, App>::value;

Но компиляция не идет:
../src/src/main.cpp: In function ‘void criticalError(QString)’:
../src/src/main.cpp:65:46: error: ‘remove_pointer_t’ is not a member of ‘std’
     qDebug() << "Value: " << std::is_base_of<std::remove_pointer_t<decltype(qApp)>, App>::value;
                                              ^~~
../src/src/main.cpp:65:46: error: ‘remove_pointer_t’ is not a member of ‘std’
../src/src/main.cpp:65:82: error: wrong number of template arguments (1, should be 2)
     qDebug() << "Value: " << std::is_base_of<std::remove_pointer_t<decltype(qApp)>, App>::value;
                                                                                  ^
In file included from /opt/qt_5_9_2/5.9.2/gcc_64/include/QtCore/qglobal.h:45:0,
                 from /opt/qt_5_9_2/5.9.2/gcc_64/include/QtGui/qtguiglobal.h:43,
                 from /opt/qt_5_9_2/5.9.2/gcc_64/include/QtGui/qguiapplication.h:43,
                 from /opt/qt_5_9_2/5.9.2/gcc_64/include/QtGui/QGuiApplication:1,
                 from ../src/src/main.cpp:1:
/usr/include/c++/6/type_traits:994:12: note: provided for ‘template<class, class> struct std::is_base_of’
     struct is_base_of;
            ^~~~~~~~~~
../src/src/main.cpp:65:88: error: expected primary-expression before ‘>’ token
     qDebug() << "Value: " << std::is_base_of<std::remove_pointer_t<decltype(qApp)>, App>::value;
                                                                                        ^
../src/src/main.cpp:65:89: error: ‘::value’ has not been declared
     qDebug() << "Value: " << std::is_base_of<std::remove_pointer_t<decltype(qApp)>, App>::value;
                                                                                         ^~
Makefile:1337: recipe for target 'main.o' failed

Я хрен знаю почему не компилится, cppreference вроде говорит что нужен только заголовок <type_traits>:

http://en.cppreference.com/mwiki/index.php?title=Special:Search&search=re...

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от pon4ik

Таки житхаб говорит, что как минимум когда то я был прав.

Что ты имеешь в виду?

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

твоего фаирвола

Не мой, рабочий.

https://www.dropbox.com

ЛОЛ, нет :) Если действительно хочется показать, то mega.co.nz вроди пускает

KennyMinigun ★★★★★
()
Ответ на: комментарий от anonymous

Пфф. reinterpret_cast

Угу, лучше сразу тогда в ногу стрелять и не париться такими формальностями.

KennyMinigun ★★★★★
()
Ответ на: комментарий от Xintrea

Я хрен знаю почему не компилится, cppreference вроде говорит что нужен только заголовок <type_traits>

Ну да, все данное добро в type_traits. std::remove_pointer_t из С++14. Попробуй версию для С++11 (я надеюсь у тебя не C++03)

std::is_base_of<typename std::remove_pointer<decltype(qApp)>::type, App>::value

KennyMinigun ★★★★★
()
Последнее исправление: KennyMinigun (всего исправлений: 1)
Ответ на: комментарий от pon4ik

Ну да, унаследовал App от QApplication, и сборка поехала.

Но почему ошибка была такая:

error: invalid static_cast from type ‘QApplication*’ to type ‘App*’

?

Ведь компилер не написал что не может сделать static_cast с QGuiApplication* на App*. Он написал что не может с QApplication* на App*. Унаследовался от QApplication, и теперь блин может. Что за дела?

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Может глянешь во что макрос разворачивается?

Как это сделать быстрее всего?

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Лень проверять, вангую в #include <QtGui> (который нафик кстати не нужен) макрос qApp переопределился.

pon4ik ★★★★★
()
Ответ на: комментарий от KennyMinigun

Попробуй версию для С++11 (я надеюсь у тебя не C++03)
std::is_base_of<typename std::remove_pointer<decltype(qApp)>::type, App>::value

В общем, результат:

Is base of:  false

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Зачем вообще создавать новый класс App только лишь для хранения публичного мембера, да ещё и макрос делать для доступа к нему? Сделай свой Core синглтоном, и если так любишь макросы, то и макрос #define CORE Core::instance()

former_anonymous ★★★
()
Ответ на: комментарий от Xintrea

по сути дела - очевидно, что где-то (возможно даже в Qt-шных хедерах) подключается <QApplication>, из-за чего qApp переопределяется. Очевидно, что твой макрос должен выгладеть так:

#define APPCORE static_cast<App*>(qGuiApp)->core


А ещё лучше не городить такой бред, а сделать Core синглтоном.

former_anonymous ★★★
()
Ответ на: комментарий от Xintrea

Еще одно подерждение, что qApp возвращает не то, что ожидаешь.

KennyMinigun ★★★★★
()
Ответ на: комментарий от former_anonymous

Зачем вообще создавать новый класс App только лишь для хранения публичного мембера, да ещё и макрос делать для доступа к нему? Сделай свой Core синглтоном, и если так любишь макросы, то и макрос #define CORE Core::instance()

Да, надо бы так переделать. Просто я только пару недель назад узнал, что синглтон в плюсах - это не только механизм, гарантирующий единственность экземпляра класса. Оказывается, используя его, не нужно таскать везде указатель на экземпляр, достаточно подключить заголовок и обратиться к статическому методу instance().

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

О сколько нам открытий чудных, гугли синглтон Мейерса, а потом гугли статью от Саттера (вроде бы, могу ошибаться), почему оно не актуально начиная с 11го стандарта.

DELIRIUM ☆☆☆☆☆
()
Последнее исправление: DELIRIUM (всего исправлений: 1)
Ответ на: комментарий от former_anonymous

патамушта

А ещё можно вот так:

std::unique_ptr<CSingleton> CSingleton::m_instance;
std::once_flag CSingleton::m_onceFlag;
 
CSingleton& CSingleton::GetInstance()
{
    std::call_once(m_onceFlag,
        [] {
            m_instance.reset(new CSingleton);
    });
    return *m_instance.get();
}
DELIRIUM ☆☆☆☆☆
()
Последнее исправление: DELIRIUM (всего исправлений: 1)
Ответ на: комментарий от Xintrea

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

И еще, ты уверен что эмитишь ПОСЛЕ того как завелся ивент луп?

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

Там про thread-safe(хотя, может я невнимательно смотрел). Всё из-за трудностей в реализации?

Deleted
()
Ответ на: комментарий от Deleted

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

deep-purple ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.