Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.138.105.31] |
|
Сообщ.
#1
,
|
|
|
Здраствуйте друзья, у меня тут очередной затык
вот хочу поюзать сабжу: typedef CArray<CString, LPCTSTR> CArrayStr; CArray<CArrayStr> arrayArrays; CArrayStr values; CString s; for (int i = 0; i < 10; ++i) { for (int k = 0; k < 100; ++k) { s.Format(_T("%d"), i); values.Add(s); } arrayArrays.Add(values); } а он пишет: "error C2248: 'CObject::operator =' : cannot access private member declared in class 'CObject'" понятно что operator = нет доступа, но что делать то?! |
Сообщ.
#2
,
|
|
|
Цитата Cfon @ понятно что operator = нет доступа, но что делать то?! Не писать так. Добавлено Используй std::vector<CArrayStr> Добавлено Цитата KILLER @ Используй std::vector<CArrayStr> Вернее наоборот, я напутал, в тайпдефе вектор используй. CArray нельзя копировать, вектор можно: typedef std::vector<CString> CArrayStr; CArray<CArrayStr, CArrayStr> arrayArrays; CArrayStr values; CString s; for (int i = 0; i < 10; ++i) { for (int k = 0; k < 100; ++k) { s.Format(_T("%d"), i); values.push_back(s); } arrayArrays.Add(values); } Добавлено Либо как вариант можешь написать свой класс, и отнаследоваться от CArray и там реализовать копирование. |
Сообщ.
#3
,
|
|
|
Цитата KILLER @ Цитата Cfon @ понятно что operator = нет доступа, но что делать то?! Не писать так. Скрытый текст Добавлено Используй std::vector<CArrayStr> Добавлено Цитата KILLER @ Используй std::vector<CArrayStr> Вернее наоборот, я напутал, в тайпдефе вектор используй. CArray нельзя копировать, вектор можно: typedef std::vector<CString> CArrayStr; CArray<CArrayStr, CArrayStr> arrayArrays; CArrayStr values; CString s; for (int i = 0; i < 10; ++i) { for (int k = 0; k < 100; ++k) { s.Format(_T("%d"), i); values.push_back(s); } arrayArrays.Add(values); } Либо как вариант можешь написать свой класс, и отнаследоваться от CArray и там реализовать копирование. я так и делал в своем демо (которое супер-пупер ) создавал класс, но теперь потребовался массив массивов CArray, а тут такие пироги лана пока сделаю через вектор, но не люблю мешать разные библиотеки. Добавлено не я один работаю на MFC http://stackoverflow.com/questions/4168964...-results-in-mfc |
Сообщ.
#4
,
|
|
|
Цитата Cfon @ я так и делал в своем демо (которое супер-пупер ) создавал класс, но теперь потребовался массив массивов CArray, а тут такие пироги лана пока сделаю через вектор, но не люблю мешать разные библиотеки. Добавлено 5 минут назад не я один работаю на MFC http://stackoverflow.com/questions/4168964...-results-in-mfc Я бы так не заморачивался на самом деле. Очень часто, многие неверно понимают задачу, вернее не так, очень часто, многие выбирают неверное решение или не совсем верное решение для своей задачи, возможно из за отсутствия опыта. Порой по другому - сделать проще. Но не зная условия задачи - сложно будет подсказать более правильное решение. Вообще я например редко когда использую массив массивов, так как это усложняет работу с объектом. Может быть в твоем случае можно сделать более проще? Плюс ко всему, когда ты пишешь на MFC логику, не интерфейс, то учитывай то, что ты привязываешься к MFC. И если вдруг через пол года тебе вздумается переписать это все под какую нибудь другую ГУИ, например QT, то это будет очень трудозатратным. Поэтому логику работы лучше вообще не привязывать к конкретным API, а писать ее используя стандартные контейнеры, благо функционала там хватает с головой. И отделять это все от MFC. Тогда, в случае чего у тебя получится более универсальный продукт, который в конечном итоге ты сможешь прикрутить к разным ГУЯМ, а то и сделать поддержку нескольких. |
Сообщ.
#5
,
|
|
|
Цитата KILLER @ Я бы так не заморачивался на самом деле. Очень часто, многие неверно понимают задачу, вернее не так, очень часто, многие выбирают неверное решение или не совсем верное решение для своей задачи, возможно из за отсутствия опыта. Порой по другому - сделать проще. Но не зная условия задачи - сложно будет подсказать более правильное решение. Вообще я например редко когда использую массив массивов, так как это усложняет работу с объектом. Может быть в твоем случае можно сделать более проще? Плюс ко всему, когда ты пишешь на MFC логику, не интерфейс, то учитывай то, что ты привязываешься к MFC. И если вдруг через пол года тебе вздумается переписать это все под какую нибудь другую ГУИ, например QT, то это будет очень трудозатратным. Поэтому логику работы лучше вообще не привязывать к конкретным API, а писать ее используя стандартные контейнеры, благо функционала там хватает с головой. И отделять это все от MFC. Тогда, в случае чего у тебя получится более универсальный продукт, который в конечном итоге ты сможешь прикрутить к разным ГУЯМ, а то и сделать поддержку нескольких. я пока так не умею мыслить в перспективе пишу гавнокод, потом рефакторинг, потом опять гавнокод и тд но за совет спс будем стараться Добавлено как уже сказал не лежит мешать std::vector c MFC СArray + CString хз почему чисто мое субъективное.. для практики решил поюзать массив указателей на массив через std::shared_ptr: typedef CArray<CString, LPCTSTR> ArrayStr; CArray<std::shared_ptr<ArrayStr>> grid; CString s; for (int i = 0; i < 10; ++i) { std::shared_ptr<ArrayStr> values(new ArrayStr); for (int k = 0; k < 100; ++k) { s.Format(_T("%d"), i); values->Add(s); } grid.Add(values); } Добавлено Цитата KILLER @ Вообще я например редко когда использую массив массивов, так как это усложняет работу с объектом. Может быть в твоем случае можно сделать более проще? в данном конкретном случае я хотел данные из запроса загрузить во временный массив и отсеить и/или отформатировать, а потом записать их в контролы диалога Добавлено вот Функция из моего демо: void CCustomDlg::FillListCtrl(CListCtrl* list, LPCTSTR query, int id) { CString qry; qry.Format(query, id); std::unique_ptr<CSqlStatement> stmt(theApp.mSQLiteDB.Statement(qry)); ASSERT(stmt); /* вставка заголовка таблицы */ CString fieldName; fieldName = _T("#"); list->InsertColumn(0, fieldName); list->SetColumnWidth(0, 50); for (int k = 1; k < stmt->Fields(); ++k) { fieldName = stmt->FieldName(k); list->InsertColumn(k, fieldName); list->SetColumnWidth(k, 100); } /* вставка данных в таблицу */ typedef CArray<CString, LPCTSTR> CArrayStr; CArray<std::shared_ptr<CArrayStr>> grid; while (stmt->NextRow()) { std::shared_ptr<CArrayStr> rows(new CArrayStr); // удаляем строки вида '(null)' for (int k = 0; k < stmt->Fields(); ++k) { if (CString(stmt->ValueString(k)) != _T("(null)")) rows->Add(stmt->ValueString(k)); else rows->Add(_T("")); } grid.Add(rows); } /* теперь пишем в CListCtrl */ LVITEM lv; lv.mask = LVIF_TEXT; CString value, n; int i = 0; for (int i = 0; i < grid.GetCount(); ++i) { lv.iItem = i; lv.iSubItem = 0; n.Format(_T("%d"), i + 1); lv.pszText = n.GetBuffer(n.GetLength()); list->InsertItem(&lv); for (int k = 1; k < grid[i]->GetCount(); ++k) { lv.iSubItem = k; value = stmt->ValueString(k); value = (*grid[i])[k]; lv.pszText = value.GetBuffer(value.GetLength()); list->SetItem(&lv); } } } можно было и без него делать, но я не ищу легких путей хотя не не так я ищу легкие пути, но не легкие в плане писанины, стараюсь больше кодить |
Сообщ.
#6
,
|
|
|
В Java есть такая хренотень называется Hibernate, в основном нужна для того, чтобы отображать таблицы в БД в виде объектов Java. Там в XML можно наколбасить специальный такой метаобъект, из него получается класс, который по сути представляет из себя описание таблицы. Я правда с этим работал давненько, в году 2015 в последний раз. Но, тем не менее, может быть тебе сделать что то подобное? Ну типа колбасишь какой то класс, который соответствует таблице в БД, связи осуществляются путем агрегирования(вот тут подробнее про этот термин можешь почитать)
С одной стороны да - есть небольшая проблема совместимости, т.е. если в таблице в БД добавится или удалится колонка, тогда придется править этот класс. Но с другой стороны, ты получаешь полноценный объект, с которым очень просто работать. Так же встречаются в некоторых АПИ такие структуры как octetsequence, допустим в древней Corba технологии такое используется, грубо говоря - это двумерный массив данных, но он нужен больше для сериализации, чем для работы с БД. Еще так же есть вариант создания POD объектов, очень часто такое встречается в С/С++, в данном случае под POD объектом имеется ввиду простая структура фиксированного размера. Т.е. вот в БД есть у тебя таблица, каждый столбик имеет ограниченный размер, например там: create table users ( id_user int (10) AUTO_INCREMENT, name varchar(20) NOT NULL, email varchar(50) NOT NULL, password varchar(15) NOT NULL, PRIMARY KEY (id_user) ); Так вот у себя в коде ты делаешь подобную структуру: struct Users { int id_user[10]; //! Это ключевое поле PRIMARY KEY char name[20]; char email[50]; char password[50]; }; Потом создаешь допустим вектор таких структур и забиваешь их данными из БД. Уже даже с этим проще работать. В твоем же случае ты используешь двумерный массив строк, как потом по типам их раскидывать? Наткнешься на грабли. Я бы делал наверное или как в Hibernate, ну или что то похожее, или через POD структуры, темболее всякие sqllite скорее всего заточены на это, т.е. скорее всего там когда тебе что то возвращается можно указывать куда писать а также сразу форматировать в разные типы данных, хотя вот конкретно с sqllite я не работал. Мне кажется так было бы проще. Добавлено Причем с POD объектами можно увеличить быстродействие, т.к. там можно сразу кусок памяти копировать, а не заморачиваться всякими операторами присваивания/конструкторами копирования и т.п. А цельный кусок данных всегда быстрее копировать, чем по частям. Добавлено Да, и с объектами/структурами тебе же потом проще будет делать декомпозицию, и получится проще. Потому как так ты знаешь с какой таблицей ты работаешь, а в твоем случае - двумерный массив, а что за таблица - легко можно провтыкать, и просидеть потом неделю в отладчике из за какой нибудь опечатки в коде. |
Сообщ.
#7
,
|
|
|
Цитата KILLER @ В Java есть такая хренотень называется Hibernate, в основном нужна для того, чтобы отображать таблицы в БД в виде объектов Java. Там в XML можно наколбасить специальный такой метаобъект, из него получается класс, который по сути представляет из себя описание таблицы. Я правда с этим работал давненько, в году 2015 в последний раз. Но, тем не менее, может быть тебе сделать что то подобное? Ну типа колбасишь какой то класс, который соответствует таблице в БД, связи осуществляются путем агрегирования Скрытый текст (вот тут подробнее про этот термин можешь почитать) С одной стороны да - есть небольшая проблема совместимости, т.е. если в таблице в БД добавится или удалится колонка, тогда придется править этот класс. Но с другой стороны, ты получаешь полноценный объект, с которым очень просто работать. Так же встречаются в некоторых АПИ такие структуры как octetsequence, допустим в древней Corba технологии такое используется, грубо говоря - это двумерный массив данных, но он нужен больше для сериализации, чем для работы с БД. Еще так же есть вариант создания POD объектов, очень часто такое встречается в С/С++, в данном случае под POD объектом имеется ввиду простая структура фиксированного размера. Т.е. вот в БД есть у тебя таблица, каждый столбик имеет ограниченный размер, например там: create table users ( id_user int (10) AUTO_INCREMENT, name varchar(20) NOT NULL, email varchar(50) NOT NULL, password varchar(15) NOT NULL, PRIMARY KEY (id_user) ); Так вот у себя в коде ты делаешь подобную структуру: struct Users { int id_user[10]; //! Это ключевое поле PRIMARY KEY char name[20]; char email[50]; char password[50]; }; Потом создаешь допустим вектор таких структур и забиваешь их данными из БД. Уже даже с этим проще работать. В твоем же случае ты используешь двумерный массив строк, как потом по типам их раскидывать? Наткнешься на грабли. Я бы делал наверное или как в Hibernate, ну или что то похожее, или через POD структуры, темболее всякие sqllite скорее всего заточены на это, т.е. скорее всего там когда тебе что то возвращается можно указывать куда писать а также сразу форматировать в разные типы данных, хотя вот конкретно с sqllite я не работал. Мне кажется так было бы проще. Причем с POD объектами можно увеличить быстродействие, т.к. там можно сразу кусок памяти копировать, а не заморачиваться всякими операторами присваивания/конструкторами копирования и т.п. А цельный кусок данных всегда быстрее копировать, чем по частям. Добавлено Да, и с объектами/структурами тебе же потом проще будет делать декомпозицию, и получится проще. Потому как так ты знаешь с какой таблицей ты работаешь, а в твоем случае - двумерный массив, а что за таблица - легко можно провтыкать, и просидеть потом неделю в отладчике из за какой нибудь опечатки в коде. да вначале была такая идея про hibernate когда то читал и даже щупал но ща опробую другой стиль программирования чисто для демо т.е. пишу как есть сходу гавнокод решаю мелкие задачи в виде шажков и потом если вдруг траблы делаю рефакторинг таким образом нубы (я тоже в какой то мере нуб ) пройдут со мной весь путь от чистого листа до готового приложения БД я надеюсь что так и будет Добавлено да и возможно потом (если будет желание) попробую переделать тоже демо-приложение через технологию ORM Добавлено цель же этого подхода дать нубам поюзать SQL ручками, т.к. сиквел основа программирования БД |
Сообщ.
#8
,
|
|
|
Цитата Cfon @ цель же этого подхода дать нубам поюзать SQL ручками, т.к. сиквел основа программирования БД Ну у тебя сейчас подход - "Как делать нельзя". Делай хотя бы через POD объекты, это будет по крайней мере легче, чем у тебя сейчас. Нубы полюбому будут смотреть последнюю версию "Как правильно", а как не правильно врятли будут смотреть. Темболее что у тебя там уже с десяток зип архивов с проектами, такими апдейтами ежедневными, к концу месяца уже их наберется около 30-40 Добавлено Цитата KILLER @ такими апдейтами ежедневными, к концу месяца уже их наберется около 30-40 Именно по этому я тебе в соседней теме и писал, что лучше потратить день на освоение СКВ, и делать правильно, тогда у тебя получится всегда актуальная версия, можно еще понаделать бранчей, для каких то тестовых проектов. |
Сообщ.
#9
,
|
|
|
Цитата Cfon @ typedef CArray<CString, LPCTSTR> CArrayStr; Здесь, наверное, следует делать CArray<CString, const CString &>. Иначе у тебя всегда будет создаваться копия строки. А так, будет отрабатывать конструктор копирования CString, который вроде как copy-on-write Добавлено Цитата Cfon @ arrayArrays.Add(values); А здесь, даже если бы скомпилировалось, то всегда создавалась бы копия массива. Оно тебе надо? У этих классов вообще, по-моему, move-конструкторов нет |
Сообщ.
#10
,
|
|
|
Цитата KILLER @ Ну у тебя сейчас подход - "Как делать нельзя". Делай хотя бы через POD объекты, это будет по крайней мере легче, чем у тебя сейчас. Нубы полюбому будут смотреть последнюю версию "Как правильно", а как не правильно врятли будут смотреть. Темболее что у тебя там уже с десяток зип архивов с проектами, такими апдейтами ежедневными, к концу месяца уже их наберется около 30-40 что значит нельзя? можно это же демо, тут все можно главное результат. я же говорю решаю проблемы по мере поступления если конечно они появляются Добавлено Цитата Олег М @ Цитата Cfon @ typedef CArray<CString, LPCTSTR> CArrayStr; Здесь, наверное, следует делать CArray<CString, const CString &>. Иначе у тебя всегда будет создаваться копия строки. А так, будет отрабатывать конструктор копирования CString, который вроде как copy-on-write Добавлено Цитата Cfon @ arrayArrays.Add(values); А здесь, даже если бы скомпилировалось, то всегда создавалась бы копия массива. Оно тебе надо? У этих классов вообще, по-моему, move-конструкторов нет да LPCTSTR по запарке пишу обычно просто CArray<CString> тот вариант вроде мне был нужен при использовании с CMap я ща не помню там с мапой простой вариант вроде не компилируется врать не буду компа нет под рукой |