LinuxForum.Fans
Тема

Инициализация static переменных (C++)

Автор: enRai 10 сообщений 8204 просмотров
#64140

Здравствуйте!
Суть задачи такова:
Необходимо читать из файла строки и при возникновении определенного ключа в считанной строке, выполнять некоторые действия.
Решил сделать так:

class a {
public:
// ...
virtual bool Read(void); // Читает строку и распихивает по переменным необходимые значения
virtual bool Write(void); // Записывает ранее считанные данные в файл в определенном порядке
static void SetHandlers(a**,int); // Устанавливает все необходимые обработчики, которые являются потомками данного класса
static bool Parse(void); // Парсит файл, вызывая необходимых потомков в зависимости от ключей в файле (Read)
static bool Append(void); // Записывает все ранее пропарсенные данные, вызывая потомков поочереди из массива (write)
protected:
// ...
static std::ifstream iFile; // поток для чтения (как инициализировать?)
static std::ofstream oFile; // поток для записи (как инициализировать?)
static std::vector<a*> Handlers; // массив с потомками-обработчиками, для записи с ключом, будет клонироваться потомок в массив Stack (как инициализировать?)
static std::vector<a*> Stack; // Массив с пропарсенными данными (как инициализировать?)
};

class b: public a {
public:
bool Read(void) { /*...*/ }
bool Write(void) { /*...*/ }
};

То есть родителем задаетются потоки для чтения/записи, которые должны использовать потомки, стек объектов пропарсенных записей, массив возможных обработчиков. Родитель вначале дает "пинок" детям, чтоб те кидались парсить файл (в ходе этого плодятся дети с готовыми данными), и после обработки полученных данных, родитель дает второй "пинок" только что наплодившимся детям, чтоб те записывали свои данные в файл.
Собственно из комментариев должна быть понятна суть проблемы и вопрос: как инициализировать статичные переменные в данном случае??

#64149

Добавьте в public еще функцию init и finit, к-е будут ответственны за начало и завершение работы.
Инициализацию статичных данных будет делать init:
поток для чтения
Дескриптор открытого файла
поток для записи
Дескриптор файла, куда будут записываться парсернные данные
массив с потомками-обработчиками
Наверное стоит создать одного потомка
Массив с пропарсенными данными
Нулевой массив. Обработанных данных ведь еще нет.

#64155

Спасибо за совет! Сейчас попробую :)
А я уже вот так начал делать:

std::ifstream *a::iFile = new std::ifstream;

Пишу прям сразу после определения класса.

По крайней мере компилятор пока перестал ругаться, как дальше будет - не знаю.

Но сделаю по вашему совету. Спасибо :)

#64184

И еще у меня вопрос по векторам. Походу я не понимаю принципа...
Вот объявление(применимо к предидущему примеру):

class a {
// ...
std::vector<a*> *Handler; // получается что это указатель на вектор из указателей на объекты класса
}

a::Handler[0] // Как я предполагаю - это указатель на объект класса

a::Handler[0]->iFile // Как предполагаю - должно быть обращение к мемберу, но пишет что это вообще и не указатель и использовать -> нельзя

// Ладно, пробуем через точку
a::Handler[0].iFile // А теперь выдает, что iFile не является мембером

Кто-нибудь сможет мне объяснить в чем тут дело?

#64188

Жесть путаница, но кажись так надо:
(*Handler)[0]->iFile
т.е. надо по указателю получить объект Vector<a*>

или так возможно прокатит: Handler[0][vector_index]->iFile

#64193

Ура! Вроде компилятор съел :) Сейчас еще надо попробовать как это все в действии будет выглядеть. Спасибо огромное за помощь!

#64290

И еще немного продолжу тему статических классов и указателей :)

class a {
/*...*/
};

class b {
static a *any;
};

Тут необходимо инициировать объект any. Но создавать заново объект крайне нежелательно. Необходимо выцепить указатель на него (или ссылку), чтобы статический класс b мог использовать уже готовый объект. Но как это сделать? Если просто объявить указатель и не инициировать его, то компилер все съест, а вот линкер поругает за то, что используется неопределенная переменная (необходимо инициировать). Для значения типа int выглядело бы так:

int b::a = 0; // Инициализируется вне объявлений функций или класса

Но вот как быть с классом? Если класс, которым необходимо инициализировать указатель, создается после объявления класса (и соответственно инициализации его переменных), да еще и имеет параметры в конструкторе, которые вычисляются в ходе работы программы?

Что-то я совсем запутался...

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

a *b::any = NULL;

Но, как и предполагал, прога в кору выпала при последующей инициализации необходимым указателем :(

#64294

Попробуйте:
class b {
static a *any = 0;
};

Нет?

Тут необходимо инициировать объект any.

Вызывайте его конструктор.

#64353
AndreyMust19 написал:
Вызывайте его конструктор.

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

#64369

Если правильно понял, то можно просто в конструкторе b класса проводить проверку на существование объекта класса А по адресу статического указателя any, и если пусто, то инициализировать:

if (b::any == NULL) b::any = new a(..);


...Необходимо выцепить указатель на него (или ссылку), чтобы статический класс b мог использовать уже готовый объект...

any - и есть указатель. Проблем с доступом из статического объекта класса Б к any быть не должно.

Войдите или зарегистрируйтесь, чтобы ответить.