Хранение адреса объекта в перменной (в БД)
[COLOR=skyblue]
TCustomWinSocket *h = sServer->Socket->Connections[0];
int hh = (int)h;
TCustomWinSocket *sck = (TCustomWinSocket *)hh;
sck->SendText ("A");
[/COLOR]
Причем целочисленная переменная hh может храниться где-нибудь в стороннем месте (например в БД). Могут ли при таком раскладе возникнуть какие-либо глюки?:devil:
Делаю следующим образом:
[COLOR=skyblue]
TCustomWinSocket *h = sServer->Socket->Connections[0];
int hh = (int)h;
TCustomWinSocket *sck = (TCustomWinSocket *)hh;
sck->SendText ("A");
[/COLOR]
Причем целочисленная переменная hh может храниться где-нибудь в стороннем месте (например в БД). Могут ли при таком раскладе возникнуть какие-либо глюки?:devil:
А кто гарантирует, что указатель *sck после его инициализации из hh в момент использования будет валиден? Другими словами, ты гарантируешь, что до sck->SendText объект не будет уничтожен (delete g;) ?
Если так, то работать будет, но этот код ОООЧЕНЬ кривой. Я уверен на 100%, что можно сделать по-нормальному без нарушения типовой безопасности.
Кроме того, сколько ты собираешься хранить таким образом указатель? Надеюсь, ты понимаешь, что при следующем запуске приложения он будет невалидным?
Причем целочисленная переменная hh может храниться где-нибудь в стороннем месте (например в БД). Могут ли при таком раскладе возникнуть какие-либо глюки?:devil:
Шутники...
А ты попробуй перезапустить программу, прочитать значение обратно из базы и применить его в качестве адреса. А потом уже спрашивай про глюки.
Личный опыт - вещь бесценная. Главное, чтобы ошибки совершаемые в процессе его постижения, не были фатальными.
В БД сохраняю только для тех целей чтобы использовать в текущем сеансе... т.е. по завершении приложения все записи в БД затираются; затирается соответствующая запись также при соответствующем OnDisconnect....
Если так, то работать будет, но этот код ОООЧЕНЬ кривой. Я уверен на 100%, что можно сделать по-нормальному без нарушения типовой безопасности.
предложи лучше...
P( ъ
предложи лучше...
P( ъ
А что тебе мешает хранить указатель, как он есть?
TCustomWinSocket*
А что тебе мешает хранить указатель, как он есть?
TCustomWinSocket*
Это условие проектирования прикладной задачи
Это условие проектирования прикладной задачи
Не понял.
Хранить в базе - условие?
Кто ставит такие дурацкие условия?
Greene!!!
в действительно сложных проектах, задачи могут быть еще по-круче.
Например ампутация гланд через...
Это не крутая задача, это плохая архитектура, плохой подход.
Почемубы не выводить тогда значения указателя на экран и просить пользователя его запомнить, что бы потом ввести по требованию системы.
настоящий программист их решает, а не возмущается. :D
Настоящий програмист сродни шахматисту а не вьючному животному.
P.S. "дурацкие" задачи обычно ставит начальство.
Не уверен, что такую задачу мог поставить руководитель проекта или архитектор. Думаю это либо просчет самого программиста по неопытности, либо задача какого-то преподавателя.
В обоих случиях советую грамотно подходить к архитектуре проекта и стилю программирования. Не
стоит лишний раз преобразовывать типы, тем более в необратимом направлении (class* -> void*, int и т.п.). И уж конечно нет смысла хранить что-то имеющее только внутреннее назначение да ешё и на столько ограниченное по времени актуальности где-то вовне.
с тобой еще не было такое, что после того, как ты написал программу, заказчика осенило и вспомнил какой-то мизер. но из-за этого мизера пришлось перекроить всю структуру программы. типа если сравнить программу с зданием, то поменять 6 этаж с 7м, между 1м и 2м поместить еще один а 3й вообще убрать.
Со мной много чего было, но как это относится непосредственно к данному случаю?
Что должно произойти в отношениях с заказчиком, что бы потребовалось сохранять указатель в БД? :D
Лирическое отступление: чтобы не получалось, как в твоем примере с этажами, надо воспользоваться хотя бы некоторыми практиками XP.
допустим есть двухмерный массив.
в первый столбец записывается код типа, нпр.
0 - ^TCustomWinSocket
1 - ^IdIOHandlerSocket
...
второй столбец адреса этих классов.
наименьший общий знаменатель это __int32.
Ты, наверное хотел сказать, адреса экземпляров классов? ;)
Если бы я программировал на языке ПОП, возможно, я так бы и поступил, но мы коворим об ООП. Поэтому я бы воспользовался интерфейсом, т.е. чисто виртуальным базовым классом. Тогда бы, кстати, и массив был бы одномерным.
Все, вопрос снят, что вы грзетесь то..? ну хотите - пожалуйста, однако форум не для этого был создан видимо...X)-
Ну и что вы завелись?
Все, вопрос снят, что вы грзетесь то..? ну хотите - пожалуйста, однако форум не для этого был создан видимо...
Мы ещё чуть-чуть... Ок? :)
и с помощью XP можно прогнозировать все те изменения, которые произойдут в бухгалтерском учете в ближайшие 5 лет?
В XP по большому счету не прогнозируется дальше текущей итерации. В этом и фишка.
это не всегда осуществимо. классы не твои. в одном класее KindOf() в другом классе TypeOf(), а в третьем класссе разработчик это и не предусмотрел.
Для этого существуют обертки.
Как ты считаешь, что проще при добавлении нового такого класса: везде в коде программы дописывать что-то типа:
{
........
case CLASS_ID_HANDLE_SOCKET:
TCustomWinSocket* p = (TCustomWinSocket*)IntVal;
p->TypeOf();
.........
}
Или один раз написать класс-обертку для нового класса?
Я применил шаблон, просто, чтоб не придумывать имена новым классам-оберткам:
{
public:
virtual int GetType() = 0;
};
template <class T>
class CWrapper :public CAbstructBase, T
{
int GetType() {return 0;} //Unknown class
};
// Добавляем классы:
template <>
int CWrapper<TCustomWinSocket>::GetType() {return 1;}
template <>
int CWrapper<TAsyncWinSocket::GetType() {return TypeOf();}
template <>
int CWrapper<TSyncWinSocket::GetType() {return KindOf();}
// Появился новый класс TNewWinSocket, дописываем
template <>
int CWrapper<TNewWinSocket>::GetType() {return 213;}
Этот процесс можно автоматизировать так, что вообще ничего нового писать непридется. Могу набросать код, но если Вы плохо знаете С++, то боюсь, Вам сложно будет разобраться
будь добр, если не составит тебе труда. Меня бы интересовал этот код.
Greene, ты можешь написать хоть один ответ так, чтоб там небыло флюида? :D
Флюид(ы) - гипотетические жидкости передающие свойства одного объекта другому(алхимия).
Флуд(flood) - треп, бессодержательный разговор(жаргон), наводнение.
Судя по всему, плохо не только с С++:)
будь добр, если не составит тебе труда. Меня бы интересовал этот код.
Это заголовочный файл, в котором собственно все и заключено:
CIDManager - менеджер ID, который назначает классам их ID,
CBase - базовый класс-интерфейс, для доступа к классам обернутым и сложенным куда-нибудь в массив или контейнер(для контейнера надо немного доработать),
CIDWrapper - класс-обертка для оборачивания классов и назначения им ID.
В процессе работы этот заголовочник никак не изманяется при добавлении/удалении классов в проект.
#ifndef _CLASSMANAGER_H_
#define _CLASSMANAGER_H_
// Класс(синглтон) раздающий ID
class CIDManager
{
public:
static long GetID()
{
static CIDManager instanse;
return instanse.lastID++;
}
private:
long lastID;
// Т.к. класс - синглтон, запрещаем создание экземпляров извне
CIDManager() :lastID(1) {}
~CIDManager(){}
CIDManager& operator= (const CIDManager&) {}
};
// Базовый абстрактный класс - интерфейс
class CBase
{
public:
virtual long GetID()=0;
};
// Шаблонный класс - обертка
template<class T>
class CIDWrapper :public T, public CBase
{
public:
long GetID() {return classID;}
static const long classID;
};
// При создании КЛАССА (инстанировании шаблона), он автоматически получает ID
template<class T>
const long CIDWrapper<T>::classID = CIDManager::GetID();
#endif _CLASSMANAGER_H_
Теперь пример использования:
#include <stdio.h>
#include "ClassManager.h"
// Два произвольных класс для тестирования
class A {};
class B {};
#define PRINT_CLASS_ID(n) printf(#n" class ID = %u\n", n.GetID());
int main()
{
CIDWrapper<A> a;
CIDWrapper b;
// Проверяем, что ID у класса постоянный
CIDWrapper<A> c;
CIDWrapper d;
PRINT_CLASS_ID(a)
PRINT_CLASS_ID(b)
PRINT_CLASS_ID(c)
PRINT_CLASS_ID(d)
// Проверяем в купе с интерфейсом
CBase* array[] = {&a, &b, &c, &d};
for(int i=0; i<sizeof(array)/sizeof(array[0]); i++)
printf("%i class ID = %u\n", i, array->GetID());
}
Greene, ты можешь написать хоть один ответ так, чтоб там небыло флюида? :D
Я люблю поспорить. Это совсем другое дело. :D