244 / 164 / 133
Регистрация: 30.09.2012
Сообщений: 690
|
||||||||||||||||
1 | ||||||||||||||||
Шаблонный класс. Ошибка : aggregate 'Box<info*> ob' has incomplete type and cannot be defined17.11.2014, 23:04. Показов 5099. Ответов 15
Метки нет (Все метки)
Здравствуйте!
Снова возникла небольшая проблема. Создал шаблонный класс: box.h Кликните здесь для просмотра всего текста
Хранить собираюсь базовый класс и наследник: Кликните здесь для просмотра всего текста
Создаю объект так:
ошибка: aggregate 'Box<info*> ob' has incomplete type and cannot be defined На форуме и в интернете ответа на этот вопрос не нашел, поэтому надеюсь на вашу помощь! Также есть проблема с выделением памяти в функциях read и operator= под класс наследник (infoD), так как если с info все понятно (пишу, например, temp = new X(...) ), то с наследником проблема. Как это реализовать? Заранее спасибо!
0
|
17.11.2014, 23:04 | |
Ответы с готовыми решениями:
15
Алгоритм хеширования, ошибка "aggregate 'HMAC_CTX ctx' has incomplete type and cannot be defined" Не компилируется простейший файл (aggregate 'QString sss' has incomplete type and cannot be defined) Ошибка "aggregate 'main()::mmm x' has incomplete type" Ошибка `user-defined type not defined`. VBA для OneNote |
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
|
|
17.11.2014, 23:35 | 2 |
А где, собственно, реализация шаблона Box-то?
Доступной в единице трансляции реализации нет - это и есть причина ошибки.
1
|
244 / 164 / 133
Регистрация: 30.09.2012
Сообщений: 690
|
||||||||||||||||||||||||||
18.11.2014, 00:00 [ТС] | 3 | |||||||||||||||||||||||||
DrOffset, Не совсем понял вопрос
Я же реализовал его в box.h, а в info.h написал предварительное объявление класса, чтобы использовать дружественные функции(сейчас они закомментированы чисто для отладки). Или я так не могу написать? То есть, например, данная запись:
update: Когда убрал в info эту запись:
ошибка: expected initializer before '<' token Пишу так:
Тут я вообще потерялся. Например, со списком я ведь делал также:
Не по теме: С собственными шаблонами работаю впервые, поэтому извините за, возможно, глупые вопросы :pardon:
0
|
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
|
||||||||||||||||
18.11.2014, 00:10 | 4 | |||||||||||||||
Gr1f0nn, В месте использования Box должен быть полностью определен. Но по твоему коду не очень понятно где именно ты пишешь вот это:
Добавлено через 46 секунд Ее не надо убирать. Нужно в месте использования шаблона обеспечить его полное определение. Вот и все. Добавлено через 5 минут Gr1f0nn, По поводу friend, писать надо так:
1
|
244 / 164 / 133
Регистрация: 30.09.2012
Сообщений: 690
|
||||||||||||||||
18.11.2014, 00:14 [ТС] | 5 | |||||||||||||||
DrOffset, Кажется понял, о чем вы.
Теперь компилятор на это не ругается ^_^ За разъяснения с дружественными функциями отдельное спасибо! У меня остался только один вопрос по поводу класса info и производного от него infoD. Так как у меня шаблон задается так:
Например, вот в этой функции:
0
|
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
|
|||||||||||||||||||||
18.11.2014, 03:45 | 6 | ||||||||||||||||||||
Как-то автоматически это сделать нельзя.
Предлагаю следующее. Инстанцировать шаблон, не базовым типом, а производным:
В производном классе завести typedef который будет псевдонимом для базового, например так:
1
|
244 / 164 / 133
Регистрация: 30.09.2012
Сообщений: 690
|
||||||||||||||||
18.11.2014, 15:43 [ТС] | 7 | |||||||||||||||
DrOffset, Спасибо, кажется, начинаю понимать Ваш ход мыслей
Так как я храню несколько типов данных в одном контейнере, то я должен хранить указатели на эти объекты, поэтому и пишу не info, а info*. Когда делал что-то подобное с библиотечным списком, то делал также :
Насчет полной формулировки задачи: Необходимо создать класс-контейнер, в котором будет храниться пользовательский базовый-класс и класс-наследник. Класс-контейнер реализовать с помощью шаблона. Вот полный код: Box.H Кликните здесь для просмотра всего текста
info.h Кликните здесь для просмотра всего текста
0
|
244 / 164 / 133
Регистрация: 30.09.2012
Сообщений: 690
|
|||||||||||
18.11.2014, 15:44 [ТС] | 8 | ||||||||||
info.cpp
Кликните здесь для просмотра всего текста
infoD Кликните здесь для просмотра всего текста
0
|
244 / 164 / 133
Регистрация: 30.09.2012
Сообщений: 690
|
|||||||||||||||||||||||||||||||
18.11.2014, 20:11 [ТС] | 9 | ||||||||||||||||||||||||||||||
dialog.cpp
Кликните здесь для просмотра всего текста
dialog.h Кликните здесь для просмотра всего текста
Добавлено через 5 минут Насчет проблем в проектировке, то у меня с самого начала были сомнения на этот счет. В первую очередь это указатели
Добавлено через 4 часа 20 минут Если точнее, то надо, скорее всего, структуру тоже сделать шаблоном:
Теперь программа ругается как раз на эти указатели из класса info
Оно, в принципе, и понятно, ведь шаблон не имеет доступа к этим указателям (или тут дело в другом?) Структура будет решением этой проблемы или есть решение еще лучше?
0
|
244 / 164 / 133
Регистрация: 30.09.2012
Сообщений: 690
|
||||||||||||||||
18.11.2014, 22:36 [ТС] | 10 | |||||||||||||||
В итоге, после некоторых мучений, я все-таки запустил программу и она даже почти корректно работает ^_^
Основные шаблонные функции(добавить в начало\конец, удалить начало\конец\все и т.п.) работают. Вот измененный шаблон: Кликните здесь для просмотра всего текста
Не работает на данный момент функция read Кликните здесь для просмотра всего текста
Сделал, как Вы посоветовали, то есть написал
Выдает такую ошибку: Код
ошибка: 'info*' is not a class, struct, or union type Код
ошибка: no match for 'operator>>' in 'fin >> temp'
0
|
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
|
||||||
19.11.2014, 00:05 | 11 | |||||
Ну советовал-то я не так А совсем наоборот. Это, по крайней мере, не ломало логику.
Выносить информацию о наследнике в базовый класс - это практически всегда лишает программу логики. Зачем в таком случае вообще это разделение на наследника и базовый класс, если мы рушим инкапсуляцию, наделяя базовый класс знанием о наследнике? Легче в таком случае все реализовать в одном классе и не мучится. К тому же ты опять начал передавать параметром шаблона тип указателя (я выше задавал наводящий вопрос об этом), соответственно после подстановки у тебя появился
Инстанцировать шаблон надо типом info, а не info*.
1
|
244 / 164 / 133
Регистрация: 30.09.2012
Сообщений: 690
|
|
19.11.2014, 08:39 [ТС] | 12 |
DrOffset, да, поздно я понял, что ерунду написал ^_^
Насчет того, что я передаю в параметр шаблона тип указателя, а не сам тип, то вот чем я руководствовался: Если бы я хранил в контейнере только один тип данных, то я бы передавал info , а не info*, а так как я храню несколько типов данных, то я никак не могу хранить сами объекты, я могу хранить только указатели на них ( или я не прав?) Собственно, опирался на опыт решения подобной задачи, но с использованием стандартных контейнеров ( в данном случае list) , где я также передавал не сам тип, а казатель на тип данных. Или это у меня ошибка в понимании того, что именно я должен хранить? Попробую сделать с info ( может пока буду делать, разберусь как раз ^_^)
0
|
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
|
||||||||||||||||
19.11.2014, 14:41 | 13 | |||||||||||||||
Не понимаю, честно говоря, твоих затруднений. Безотносительно даже текущего твоего кода:
Посмотри на стандартный std::list, там передается именно тип элемента.
У тебя же, похоже, требовалась всегда именно последняя запись, потому что на нее была завязана работа твоего списка? Похоже на то. Добавлено через 3 минуты Gr1f0nn, Если ты передаешь параметром указатель, то X = YourType *, к такому X не могут быть применены операторы разрешения области видимости ::. И код ломается. Чтобы это работало нужно передавать классовый тип. Об этом тебе и сообщил компилятор:
1
|
244 / 164 / 133
Регистрация: 30.09.2012
Сообщений: 690
|
||||||||||||||||
19.11.2014, 17:37 [ТС] | 14 | |||||||||||||||
DrOffset, Спасибо большое! Теперь все стало понятнее
Я делал так:
Как раз тут на форуме вычитал, что хранение указателей на объекты - один из способов хранения объектов разных типов. Сейчас сделал так:
Теперь буду думать, как реализовать чтение из файла\ конструктор копирования\ присваивания по-другому, так как не получается просто выделить память и под базовый класс, и под наследника в самом шаблоне. Может здесь может помочь какое-то явное преобразование типов? Хотя везде пишут, что это нежелательно делать, но все-таки вдруг ^_^
0
|
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
|
||||||
19.11.2014, 18:15 | 15 | |||||
Это так. Только разница в том, что твой класс требует выделения памяти от пользователя всегда. Указатель можно и внутри хранить, необязательно протаскивать его через весь интерфейс. Суть классов и вообще инкапсуляции в том, чтобы более сложные действия и состояния спрятать за более простым интерфейсом. Если делать класс только чтобы был, то эффекта не будет нужного
Ну как же не получается, если я выше дал тебе вполне рабочее решение (в рамках твоей текущей архитектуры)? Другие дело, что сама архитектура не очень. Но тогда нужно просто с самого начала все продумать заново. Разделить ответственности. Определить сущности их методы их взаимодействия. А потом уже код писать Не очень ясно что ты собрался преобразовывать Добавлено через 7 минут Не работало потому что так был сделан интерфейс шаблона. Нужно же всегда очень четко понимать что ты делаешь и к чему это приводит. Вслепую тыкаться и менять код наугад - плохая практика. На самом деле так даже лучше. В твоей задаче, лучше разделить ответственности. Т.е. есть класс который обобщенно (через указатели на базу) хранит указатели на экземпляры твоих объектов. А есть класс, который управляет, сохранением и восстановлением информации в\из файла. Добавлено через 18 минут Вот задача. Давай ее разберем. 1. Необходимо создать класс-контейнер с помощью шаблона. 2. В нем будут храниться пользовательский базовый-класс и класс-наследник. Сначала тебе нужно создать класс-шаблон, который будет реализовывать некий контейнер. Ну пусть это будет список. Шаблон намекает на то, что тип данных, хранимый в списке, может быть произвольно заданным. Потом, используя созданный класс, необходимо поместить в него экземпляры базового класса и экземпляры наследника. Проще всего, как ты правильно заметил, это реализовать используя полиморфизм и указатели. Теперь нужно создать некую сущность, которая объединит две предыдущие для решения задачи. Например, сохранение и восстановление информации из файла и занесение ее в наш контейнер. Итого: У нас есть класс-список, который может быть параметризован каким-либо типом. И есть два класса: базовый и наследник, которые отражают какую-то предметную область. И есть класс-менеджер, который занимается управлением данных в списке и сохранением и восстановлением в файл. Реализуя список, можно смотреть на интерфейс std::list для образца. Добавлено через 4 минуты По поводу реализации списка. Вот этот ход мыслей правильный: Только в реализации должно быть так:
node - это у нас внутренняя структура для организации списка. Навигация в памяти осуществляется через указатели на другие такие же node. При правильной реализации методы работы с node должны быть скрыты за интерфейсом list.
1
|
244 / 164 / 133
Регистрация: 30.09.2012
Сообщений: 690
|
|
19.11.2014, 19:08 [ТС] | 16 |
Вот. В этом у меня и проблема, которую я, к сожалению, обнаружил только при создании шаблона
Сейчас пробую спроектировать по-другому классы. Я подразумевал что-то вроде dynamic_cast, но опять-таки, это будет свидетельствовать о том, что класс плохо спроектирован. Кажется, уловил суть ^_^ Теперь все понятно. Если все будет спроектировано правильно, то проблем, подобным той, что есть у меня, возникнуть не должно Буду пытаться все это теперь реализовать ^_^
0
|
19.11.2014, 19:08 | |
19.11.2014, 19:08 | |
Помогаю со студенческими работами здесь
16
Ошибка 'User-defined type not defined' на ADODB.Recordset Код не работает. Ошибка User-defined type not defined. Ошибка: user-defined type not defined Ошибка return type is incomplete Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |