#c #qt #static-initialization
#c #qt #статическая инициализация
Вопрос:
Я использую Qt, но это общий вопрос C . Мой случай прост, у меня есть класс Constants
с постоянным статическим членом, который я хочу, чтобы он был инициализирован после выполнения определенных вызовов функций.
Constants.h
#ifndef CONSTANTS_H
#define CONSTANTS_H
class Constants
{
public:
static const char* const FILE_NAME;
};
#endif // CONSTANTS_H
Constants.cpp
#include "constants.h"
#include <QApplication>
const char* const Constants::FILE_NAME = QApplication::applicationFilePath().toStdString().c_str();
main.cpp
#include <QtGui/QApplication>
#include "mainwindow.h"
#include "constants.h"
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
qDebug()<< "name: "<<Constants::FILE_NAME;
//for those who are unfamiliar with Qt, qDebug just prints out
return a.exec();
}
При компиляции я получил:
QCoreApplication::applicationFilePath: Пожалуйста, сначала создайте экземпляр объекта QApplication
Итак, проблема здесь очевидна. Когда статическая функция QApplication вызывается в Constants.cpp QApplication еще не установлено Qt. Мне нужно как-то подождать, пока QApplication a(argc, argv);
строка не будет передана в main.cpp
возможно ли это, и если нет, что еще вы могли бы предложить для преодоления этого?
Спасибо
Комментарии:
1. Не объявлять его как константу? Это определенно не константа, поскольку она зависит от некоторого состояния при запуске приложения.
2. но мне нужно, чтобы он считывался только после его назначения?
3. Я могу ошибаться, но
QApplication::applicationFilePath().toStdString()
для меня это выглядит как временное, и в этом случае вы сохраняете указатель на недопустимые данные.4. Например: используйте объект (например, экземпляр класса String), присвоите ему значение NULL и проверьте, равно ли оно NULL (что означает, что он еще не назначен).
5. Вы можете использовать
.toAscii()
вместо.toStdString().c_str()
.
Ответ №1:
Типичное решение:
#ifndef CONSTANTS_H
#define CONSTANTS_H
class Constants
{
public:
static const char* const getFILE_NAME();
};
#endif // CONSTANTS_H
И в cpp
#include "constants.h"
#include <QApplication>
const char* const Constants::getFILE_NAME()
{
static const char* const s_FILE_NAME = QApplication::applicationFilePath().toStdString().c_str();
return s_FILE_NAME;
}
Комментарии:
1. Разве вы не храните указатель на содержимое временной строки? Или
toStdString()
возвращает ссылку на что-то постоянное?2. @MikeSeymour: переместить этот комментарий в OP?
3. Хороший ответ, хотя я бы предпочел пространство имен классу только со статическими членами.
4. Думаю, я согласен. Тем не менее, вышесказанное может быть типичным 🙂
Ответ №2:
Один из вариантов — вернуть его из функции, сохранив его в статической переменной. Это будет инициализировано при первом вызове функции.
char const * const file_name()
{
// Store the string, NOT the pointer to a temporary string's contents
static std::string const file_name =
QApplication::applicationFilePath().toStdString();
return file_name.c_str();
}
Комментарии:
1. Хотя 2 ответа дают одинаковый результат и работают хорошо, ваш ответ кажется более безопасным. Спасибо
2. @ValekHalfHeart: Плохая идея возвращать указатель на автоматический локальный. Этот элемент является статическим, поэтому он все еще будет существовать, когда функция вернется.
3. @MikeSeymour Правильно. Мне это никогда не приходило в голову.