Russian Qt Forum

Qt => Общие вопросы => Тема начата: kuzulis от Январь 20, 2009, 13:24



Название: Как создать объект с уникальным для него идентификатором?
Отправлено: kuzulis от Январь 20, 2009, 13:24
Доброго времени всем !

Тут столкнулся с такой задачкой:

1. например при создании какого нибудь класса (оператором new) необходимо как-то его идентифицировать, т.е отличать его от других таких же классов...
2. количество создаваемых таким образом классов ограничено допустим числом в 2000 штук
3. каждый такой класс "внутри" имеет некую ЦЕЛУЮ (int) переменную id ...

идея в том, чтобы из множества созданных однотипных классов отыскать класс с нужным идентификатором - и потом с ним работать!

так вот:
1. каким образом при создании класса генерировать эту переменную ID так, чтобы однозначно она определяла этот класс (т.е не повторялась и т.п.) ?
2.  может есть какие-то стандартные методы в QT?



Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: spirit от Январь 20, 2009, 13:27
сделайте статическую переменную в классе и в конструкторе инкрементируйте ее.


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: kuzulis от Январь 20, 2009, 13:41
а если я хочу и удалять объекты к примеру... то не напасешься разрядностью этого счетчика

например
1. создал 2000 объектов, Cnt=1-2000,
2. удалил из них 1000
3. создал еще 1000 -> Cnt=2001-3000 !!! (т.е не используются те значения ID которые были в удаленных мною объектах)

 т.е получается нифига не экономия!

ЗЫ: я раньше так делал... но это не то


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: pastor от Январь 20, 2009, 13:45
1. как уже предложил спирит, использовать статический член класс:

Код
C++ (Qt)
class YourClass
{
...
private:
  static int objectsCount = 0;
  int id;
};
 
YourClass::YourClass()
{
...
   id = objectsCount++;
...
}

При этом, objectsCount будет содержать общее кол-во созданных объектов.

2. А если просто использовать QMap? Например:

QMap<int, YourClass *> list;

при этом, ключ будет id вашего класса.


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: spirit от Январь 20, 2009, 13:47
а если я хочу и удалять объекты к примеру... то не напасешься разрядностью этого счетчика

например
1. создал 2000 объектов, Cnt=1-2000,
2. удалил из них 1000
3. создал еще 1000 -> Cnt=2001-3000 !!! (т.е не используются те значения ID которые были в удаленных мною объектах)

 т.е получается нифига не экономия!

ЗЫ: я раньше так делал... но это не то
что значит "неэкономия"? после удаления объектов уже ж не будет, а какая разница с какого числа будет айди начинаться?

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


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: Rcus от Январь 20, 2009, 13:50
если у вас объекты некопируемы, то что мешает в качестве уникального идентификатора объекта использовать указатель на него?(они совершенно точно уникальны в каждый момент времени и используются заново :)) Хотя конечно если нужно хранение идентификаторов, то такой способ не подходит


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: kuzulis от Январь 20, 2009, 13:55
Цитировать
Хотя конечно если нужно хранение идентификаторов, то такой способ не подходит
да! именно эти ID-ы должны храниться в БД...

Цитировать
что значит "неэкономия"? после удаления объектов уже ж не будет, а какая разница с какого числа будет айди начинаться?

а если объектов не 2000 а 200000! и например в процессе "конфигурирования" приложения - придется удалять/добавлять новые объекты... при этом счетчик будет делать ++ ... но счетчик - не резиновый!

и например после определенного кол-ва добавлений/удалений объектов - счетчик просто переполнится ! так что это решение - на крайняк , если ничего лучше не придумается :)


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: spirit от Январь 20, 2009, 13:58
декрементируйте в деструкторе  ;)


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: kuzulis от Январь 20, 2009, 14:05
Цитировать
декрементируйте в деструкторе  Подмигивающий

не покатит! (увы) :)


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: Rcus от Январь 20, 2009, 14:07
Интересно все же, какой смысл хранить эти идентификаторы во внешнем хранилище, если время жизни объекта настолько мало, что вы боитесь переполнения целочисленного счетчика?


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: spirit от Январь 20, 2009, 14:09
Интересно все же, какой смысл хранить эти идентификаторы во внешнем хранилище, если время жизни объекта настолько мало, что вы боитесь переполнения целочисленного счетчика?
+1


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: kuzulis от Январь 20, 2009, 14:27
Цитировать
Интересно все же, какой смысл хранить эти идентификаторы во внешнем хранилище, если время жизни объекта настолько мало, что вы боитесь переполнения целочисленного счетчика?
+1

:) оно не мало! оно велико!

я наверное плохо обрисовал ситуевину:
1. при конфигурировании приложения (создании/удалении) объектов - информация о них сохраняется в БД (сохраняется и их ID)
2. ID необходим, чтобы к этим объектам можно было "привязать" другие объекты!
3. у других объектов - в БД храниться инфа : их ID + ID того объекта к которому их нужно привязать!.

т.е при старте приложения ( рабочий режим) происходить должно следующее:
1. сканируется БД "родительских объектов"
2. по информации, записанной в ней - создаются эти объекты в оперативной памяти (+ им присваиваются уникальные ID-ы которые были сохранены в их БД)
3. сканируется БД "дочерних" объектов.
4. по информации, записанной в этой БД (БД хранит не только ID дочернего но и ID родительского объекта) - создаются эти дочерние объекты со своими параметрами + создаются они в тех родительских объектах в которых ID-ы совпадают!!!

т.е ID-ы должны быть уникальными, чтобы все было нормуль!

ЗЫ: просто я смотрю наверное на все это не с позиции "чистого" программиста куллхацкера - а с позиции алгоритмиста АСУТП :)
поэтому и по-другому наверное выражаюсь


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: pastor от Январь 20, 2009, 14:32
2 kuzulis: возми не int, a unsigned int (что более логично) Это 4294967295 объектов. Мало? Возмите unsigned long long если позволяет платформа, это 18446744073709551615 объектов. Но думаю unsigned int  для вашей задачи будет достаточно.


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: spirit от Январь 20, 2009, 14:32
а если айди при создании устанавливать в "0", а после записи в БД выгребать уникальный айди , который сгенерила база?


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: kuzulis от Январь 20, 2009, 14:34
2pastor ?

;D спс канешн.. я об этом думал.. но решил спросить тута.. может что-то в QT такое есть само по себе? :)

ну... что-то вроде как в винде дескрипрор на что-то там.. его же само ядро ОС генерит.. и он уникальный! (наверное) :)
 


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: pastor от Январь 20, 2009, 14:38
ну... что-то вроде как в винде дескрипрор на что-то там.. его же само ядро ОС генерит.. и он уникальный! (наверное) :)

Дискрипотор это тоже какой-то интергральный тип, который имеет свой придел :)


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: kuzulis от Январь 20, 2009, 14:40
Цитировать
а если айди при создании устанавливать в "0", а после записи в БД выгребать уникальный айди , который сгенерила база?

а как база сама сгенерит?


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: spirit от Январь 20, 2009, 14:46
primary key -- может генирится самой базой, как это делается зависит от конкретного сервера:
в MYSQL -- при создании таблы добавляется AUTO_INCREMENT,
в Oracle -- клепается последовательность (sequence),
в PostgreSql -- при создании таблы добавляется SERIAL,
в SqLite -- вроде так же как и в MySql (точно не помню).
получать этот айди можно через QVariant QSqlQuery::lastInsertId () const, но для Oralce & PostgreSql не возвращает.
для них я получал айди самописным методом.
но имхо, самый быстрый вариант -- это тот , о котором говорил я и пастор.


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: kuzulis от Январь 20, 2009, 14:58
ОК :)

спс... буду делать через счетчик.


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: lit-uriy от Январь 20, 2009, 15:15
вообще задачка по ID объекта из области "именованного/нумерованого одиночки", я думаю такой вариант и надо использовать.


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: Winstrol от Январь 20, 2009, 15:32
Нужно будет завести словарь  std::map<IdInDBType,KewlClass*> и в рантайме конвертировать ID в указатель на объект. 


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: kuzulis от Январь 20, 2009, 15:51
Цитировать
вообще задачка по ID объекта из области "именованного/нумерованого одиночки", я думаю такой вариант и надо использовать.
я не понял ничего :)

Цитировать
Нужно будет завести словарь  std::map<IdInDBType,KewlClass*> и в рантайме конвертировать ID в указатель на объект. 

а по подробнее идею растолкуйте :)


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: Winstrol от Январь 20, 2009, 15:54
primary key -- может генирится самой базой, как это делается зависит от конкретного сервера:
Давно с БД не имел дела, но на край на SQL можно эмулировать авто инкремент как-то так select max(ID)+1 from ...


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: spirit от Январь 20, 2009, 15:56
primary key -- может генирится самой базой, как это делается зависит от конкретного сервера:
Давно с БД не имел дела, но на край на SQL можно эмулировать авто инкремент как-то так select max(ID)+1 from ...
можно, но зачем велосипед изобретать, если все уже есть?  ;)


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: panAlexey от Январь 20, 2009, 16:47
Автоинкремент в данном случае не подходит.
Я так понимаю, что у него разные классы, а следовательно автоинкременные значения могут попросту совпасть.
Если конечно у него экземпляры классов хранятся в разных таблицах.
Если в одной, то - ОК.
Если в разных, то сводная таблица+транзакция или составное значение: видКласса+ID объекта.


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: Dendy от Январь 20, 2009, 17:52
А в каком виде вам нужен этот уникальный идентификатор? Я так понимаю - это целое неповторяющееся число из определённого диапазона с возможностью утилизировать удалённые идентификаторы во избежание переполнения счётчика. Верно?


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: lit-uriy от Январь 20, 2009, 17:58
Цитировать
вообще задачка по ID объекта из области "именованного/нумерованого одиночки", я думаю такой вариант и надо использовать.
я не понял ничего :)
Это шаблон проектирования такой - "одиночка", он же "singleton"


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: kuzulis от Январь 21, 2009, 08:37
Цитировать
А в каком виде вам нужен этот уникальный идентификатор?

в любом, который можно сохранить либо в конф. файле или БД ... + чтобы меньше памяти занимал + чтобы скорость работы была высокая

Цитировать
Я так понимаю - это целое неповторяющееся число из определённого диапазона с возможностью утилизировать удалённые идентификаторы во избежание переполнения счётчика. Верно?

ага... и не только удалять, но и использовать для вновь создаваемых объектов идентификаторы ранее удаленных объектов

---
я пока алгоритм такой наваял:

(при создании нового объекта вручную)
1. счетчик = 0
2. создаем объект
3. инкремент счетчика (т.е ID-ы будут от 1 до ....)
4. проверяем ID-ы уже имеющихся объектов и сравниваем их значения с текущим значением счетчика..
5. если есть совпадения ID-ов - переход к п. 3
6. присваиваем созданному объекту ID = тек. значение счетчика...

(при создании объектов автоматически - т.е при чтении конфига БД)
1. проверку на повторяющиеся ID-ы не делаем, т.к подразумеваем что в БД все ID-ы уже разные и все там правильно


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: kirill от Январь 21, 2009, 11:26
Алгоритм полного перебора, мягко говоря, неоптимален по времени.
А может использовать ID, создаваемый таймером ?

#include <time.h>
clock_t ID = clock();


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: kuzulis от Январь 21, 2009, 12:40
Цитировать
Алгоритм полного перебора, мягко говоря, неоптимален по времени.
А может использовать ID, создаваемый таймером ?

#include <time.h>
clock_t ID = clock();

а этот ID разве не может повториться ?


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: pastor от Январь 21, 2009, 12:46
Алгоритм полного перебора, мягко говоря, неоптимален по времени.

+1

Если вы боитесь переполнить unsigned int (а это 4294967295 объектов), то подумайте над производительностью вашего алгоритма генерирования ID. Ва нужно будет всегда пробегать по всем объектам и искать повторения.

Но, ваш алгоритм можно улучшить, путем хранения ID в списке и предварительной его сортировки перед началом его работы.


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: pastor от Январь 21, 2009, 12:50
а этот ID разве не может повториться ?

Цитировать
The clock function's era begins (with a value of 0) when the C program starts to execute. It returns times measured in 1/CLOCKS_PER_SEC (which equals 1/1000 for Microsoft C).


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: kirill от Январь 21, 2009, 12:54

а этот ID разве не может повториться ?

Это количество милисекунд от начала новой эры, сиречь 1 января 1970 года.


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: kuzulis от Январь 21, 2009, 13:06
Спасибо всем за помощь!

буду пробовать! :)


Название: Re: Как создать объект с уникальным для него идентификатором?
Отправлено: Dendy от Январь 21, 2009, 14:01
Кажется я понял что вам нужно. Для себя написал небольшой класс для этой задачи, но тем не менее он уже используется у меня в проекте в нескольких местах - уже больно полезный оказался.

http://dendy.org.ua/idgenerator.zip

Единственно что вам нужно в него добавить - сериализацию/десериализацию, а также возможность выбора собственных идентификаторов, если вы их где-то сохраняете.