C++, капелька STL: Как правильно сделать?

0000

Имеется сущность с пачкой (~10) простых (int, string) характеристик, которые надо будет получать и задавать.
Этих сущностей в программе будет кучка (грубо говоря читаются из файла при запуске проги). Так же будут циклы по всем, т.е. что то в духе:

Пройти по всем, которые имет третий параметр = 3, прочитать у них 5-ый параметр и установить 7-ой равный 10.

Поскольку С++ знаю плохо, то вначале сделал так:
определил в .h-файле тип TObject через typedef и несколько extern-функций, реализацию кинул в cpp. Список объектов (std::vector) определил глобально.
Поскольку сейчас сел переписывать все с нуля (процедурный код что то громозок и уже перестал быть управляемым то вот подумал что лучше через класс все сделать, только вот стоит ли - поскольку все static-методы будут те, что я описал extern, а другие - это обчные аксессоры? Ну может если как нить исхитрится, то можно список запихать в static-private область класса...
Плиз подскажите что нить :)
P.S. Я не силен в С++, так что сильных изысков не предвидится.

klyv

#include <vector>
#include <string>
#include <sstream>

class It
{
int Field, Field1;
public:
int getField { return Field; }
int getField1 { return Field1; }
void setField(int p) { Field = p; }
void setField1(std::string p) { std::ostringstream(p) >> Field1; }
}

std::vector<It> MyBigCollection;
без проверок, без всего. всё в .h - и всё тип-топ.

pitrik2

я не понял как то что ты предложил соотносится с тем что спрашивал автор :(
я не один?

klyv

напрямую.
я показал, ка квыглядит примерно С++ с STL, точнее - как объявить класс и коллекцию его объектов, что ему и надо было (по крайней мере, примерно)

evgen5555

Тут, по-моему, лучше подходит не вектор, а map

evgen5555

Код нерабочий

0000

Код мне не нужен :), все таки кое что я и сам могу. Все в один h фаил не получается - нужны же еще статики.
Вектор выбран потому что порядок не нужен - нужен обычный проход по набору. Можно было бы просто массив сделать, но опасаюсь что с моими знаниями нарвусь на выход за его пределы где нить в коде.

Sanjaz

Я бы сделал так:
В заголовочном файле определил твою сущность
entity.h

#ifndef __ENTITY_H__
#define _ENTITY_H__

#include <string>

class Entity {
private:
int f1, f2, ...
std::string s1, s2, ...

public:
// constructors
// accessor methods
// other method
// no methods for input/output
};

#endif

Этот файл включаем в cpp файл в котором используем нашу сущность
main.cpp

#include <fstream>
#include <entity.h>
#include <vector>

/*Function reads entities from input stream in and fill vector of Entity*/
void ReadEntities(std::istream in, std::vector<Entity>& entities)
{
int f1, f2, ...;
std::string s1, s2, ...

while (!in.eof
{
in >> f1 >> f2 >> ...;
in >> s1 >> s2 >> ...;
entities.push_back(Entity(f1, f2, ..., s1, s2, ...;
}
}

int main(int argc, char* argv[])
{
std::vector<Entity> entities;
std::ifstream in("C:\\temp\\data.txt");
ReadEntities(in, entities);
in.close;

// enumerate entities in reverse order
for (std::vector<Entity>::reverse_iterator it = entities.rbegin; it != entities.rend; ++it)
{
Entity& e = *it;
// use entity
}
}

pitrik2

for (std::vector<Entity>::reverse_iterator it = entities.rbegin; it != entities.rend; ++it)
а че, в С++ до сих пор не добавили foreach?
даже в джаве это уже есть

0000

Есть кажись :)
Хм, как то странно, а почему загрузка Entity вне класса то?
На самом деле вопрос даже такой - использование классов уместно, при такой постановке задачи?

Sanjaz

В с++ давно есть std::for_each. Но тольк в повседневной работе не очень удобно его пользовать т.к.
туда нужно передавать функцию или функтор, который обрабатывает элемент. По-моему, проще написать цикл, чем писать такую функцию.

Sanjaz

Уместно.
Я не сделал чтение данных для класса внутри самого класса вот по каким причинам:
1) Эта загрузка зависит от формата файла. Если придется поддерживать несколько форматов файлов то будут трудности (не обойдешся одним опреатором >>, ты меняешь класс а значит перекомпиляция всего проекта). А в моем случае получается если тебе надо добавить поддержку нового формата, просто пишешь новую функцию типа ReadFromXML. И вообще, все эти функции можно поместить в отдельный модуль компиляции.
readers.h

#ifndef __READERS_H__
#define __READERS_H__

#include <entity.h>
#include <iostream>

void ReadFromPlain(std::istream&in, std::vector<Entity>& entities);
void ReadFromXML(std::istream& in, std::vector<Entity>& entities);
...
#endif

readers.cpp

#include "readers.h"

void ReadFromPlain(std::istream&in, std::vector<Entity>& entities)
{
...
}

void ReadFromXML(std::istream& in, std::vector<Entity>& entities)
{
...
}


2) Скорость компиляции. В файл entity.h не фключаются всякие fstream и iostream.

0000

Аааа :D Ну так у меня точно ридер один будет - проект то махонький.

kokoc88

туда нужно передавать функцию или функтор, который обрабатывает элемент. По-моему, проще написать цикл, чем писать такую функцию
boost::bind, std::bind1st, std::bind2nd

Sanjaz

Далее, в readers.h можно еще абстрагироваться от вектора, используя inserter - ы:
std::inserter, std::back_inserter, std::front_inserter

Sanjaz

2 , это он сейчас маленький, а потом может стать большим. Как говорится: лучше день потерять, потом за 5 минут долететь.
2 , Можно воспользоваться и этим, но я, честно говоря, не умею этим пользоваться. Хотя надо изучить

0000

Нее, большим он точно не будет :) Это так сказать демка планируется. Если в дальнейшем будет развиваться, то уже не моими силами (я все таки не прогер на С++).
Псиб за объяснения :)
Оставить комментарий
Имя или ник:
Комментарий: