Member
Статус: Не в сети Регистрация: 12.12.2003 Откуда: Уфа
Как вообще нужно шаблоны программировать - с включением или разделением? Решил делать с разделением:
Код:
export template<class T> class GraphicsModelItem : public MObject, public T { ..... }
Выдает ошибки
error C2143: syntax error : missing ';' before ''template<''
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
Member
Статус: Не в сети Регистрация: 12.12.2003 Откуда: Уфа
Daemon Привет! В чем прикол месяц назад у меня это как-то работало, выносил я в cpp файл функции члены, причем без export, но в упор не помню как . Тогда же заметил странную особенность - обычные функции выносились, а виртуальные - никак. А внутри определения класса виртуальные функции нормально работают вроде. Добавлено спустя 25 минут, 15 секунд повозился еще с этим делом, короче если просто вынести функцию, даже без export, компилируется нормально, если же она где-то используется, то вылазит ошибка линковщика.
повозился еще с этим делом, короче если просто вынести функцию, даже без export, компилируется нормально, если же она где-то используется, то вылазит ошибка линковщика.
В C++ используется модель раздельной компиляции. Единица трансляции - один cpp-файл, каждый из них компилируется абсолютно независимо от других. Т.е. компилятор, обрабатывая твой файл, в который ты вынес определения шаблонных методов, ничего не знает об использовании этих методов в других файлах. В результате скомпилируются, только те (блин, слово забыл ) методы, которые ты инстанцируешь в этом файле. Соответственно, если там ничего кроме шаблонов нет, то ничего и не скомпилируется. Так что размещай шаблоны целиком в подключаемом файле.
Member
Статус: Не в сети Регистрация: 12.12.2003 Откуда: Уфа
Но ведь в стандарт предусматривает раздельную компиляцию, я так понимаю. Даже в книжках 4х-летней давности это описано. Добавлено спустя 13 минут Еще вопросик появился - есть класс, унаследованный от двух базовых. Есть функция, принимающая указатель на первый базовый класс. Есть объект производного класса. Можно ли этой функции подсунуть указатель на этот объект, типа первого класса:
Код:
class Derived : public Base1, public Base2 { ... };
reinterpret_cast ничего не делает с указателем, и в этом ошибка и заключается. Ведь объект состоит из нескольких частей: унаследованной от Base1, унаследованной от Base2 и своей собственной. Указатель на Derived указывает, естественно, на начало объекта, и довольно часто там располагается часть Base1, но это ни кем не гарантировано. Приведение указателя на Derived к базовому типу, вообще говоря, осуществляет смещение этого указателя к началу требуемой части объекта, поэтому здесь нужен static_cast, который это и делает. А вообще указатель приводится к базовому типу автоматически, и явного приведения здесь не требуется. Добавлено спустя 1 минуту, 41 секунду З.Ы. А приводить указатель на Base2 к указателю на Base1 неправильно. Где-то у тебя ошибка в проектировании. Добавлено спустя 2 минуты, 3 секунды З.З.Ы. На раздельную компиляцию шаблонов просто забей, я ещё не видел, чтобы она где-то работала и её кто-то использовал, кроме авторов книжек.
Member
Статус: Не в сети Регистрация: 12.12.2003 Откуда: Уфа
Билли Бонс Да, вот я и думал насчет того, что фактически объект в памяти состояит из нескольких частей, и указатели как-то должны сдвигаться.
Насчет ошибки в проектировании - дело в том, что я пытаюсь прикрутить существующую библиотечную иерархию классов к своей иерархии в программе. Поэтому пришлось воспользоваться единственным возможным решением(спасибо Daemon'у за подсказку). Но это решение с точки зрения структуры программы не совсем хорошее. Если же проектировать правильно, то придется переписывать часть библиотечного кода, что тоже не есть гуд.
Member
Статус: Не в сети Регистрация: 14.01.2004 Откуда: Киев, Украина
Билли Бонс писал(а):
Приведение указателя на Derived к базовому типу, вообще говоря, осуществляет смещение этого указателя к началу требуемой части объекта, поэтому здесь нужен static_cast, который это и делает.
static_cast обязателен к использованию, если объекты используют виртуальные функции, потому как именно из-за указателя на таблицу виртуальных функций происходит смещение адреса наследуемого объекта.
kexman писал(а):
Если же проектировать правильно, то придется переписывать часть библиотечного кода, что тоже не есть гуд.
Гы, это не есть правильное проектирование, если его применение приводит к подобным вещам.
Member
Статус: Не в сети Регистрация: 12.12.2003 Откуда: Уфа
Daemon Может помнишь, ты мне уже помогал в этом вопросе. В библиотеке есть иерархия классов(порожденных от общего базового), и мне надо заиметь такую же у себя в программе, причем с добавлением своих свойств и методов в каждый класс. Ты посоветовал использовать шаблон вида
Код:
template<class T> class GraphicsModelItem : public TObject, public T { ... }
Это наверное единственное решение в данном случае. Единственное что мне в нем не нравится - это то, что в разных функциях (в других частях программы), которые используют эти объекты, приходится в качестве параметров писать GraphicsModelItem<QGraphicsItem> (QGraphicsItem - базовый библиотечный класс иерархии объектов). А это - каждый раз инстанцирование шаблонов, что мне не очень нравится. Попытался заменить в параметрах функций GraphicsModelItem<QGraphicsItem> на TObject, и приводить потом где надо к QGraphicsItem - не получилось. Добавлено спустя 5 минут, 23 секунды кстати такой вопрос - при компиляции при инстанцировании шаблонов, появляется в окне output (MSVC) сооттветствующая надпись, что-то типа [T = Класс_который_подставляется]. Почему-то этого не происходит, когда использую библиотечные шаблоны. И еще. Когда я в программе 10 раз использую vector<int> - у меня 10 экзэмпляров класса vector<int> ?
Member
Статус: Не в сети Регистрация: 14.01.2004 Откуда: Киев, Украина
kexman писал(а):
приходится в качестве параметров писать GraphicsModelItem<QGraphicsItem> (QGraphicsItem - базовый библиотечный класс иерархии объектов)
Подожди, во-первых это в компаил тайме все происходит, а во-вторых для каждого нового типа, при инстанциировании шаблона, код генерируется один раз! Не понимаю, почему тебя это заботит. Добавлено спустя 1 минуту, 41 секунду
kexman писал(а):
Когда я в программе 10 раз использую vector<int> - у меня 10 экзэмпляров класса vector<int> ?
Ыыыыы, экзепляров-то десять, но код сгенерировался один раз, иначе бы получил кучу редифинишинов.
Member
Статус: Не в сети Регистрация: 12.12.2003 Откуда: Уфа
Daemon писал(а):
но код сгенерировался один раз, иначе бы получил кучу редифинишинов.
Это я и спрашивал. Понимаю. Блин с++ настолько сложный язык, куча разных мелких ньюансов, но зато жуть как интересно.
Недавно встретился со старым знакомым. Между делом у него промелькнуло в разговоре, что он "программит на сях". Ну я начал так для интереса спрашивать как он это делает. Боже мой! Вначале он сказал, что изучить язык ему помог его друг, а книжку Страуструпа он просмотрел только на предмет синтаксиса. Он говорит, что пользуется своими библиотеками, написанными им давно, в частности для работы с комплексными числами. На мои скромные попытки объяснить, что это все уже есть и написано лучшими программерами мира, он ответил, что зато сам это написал. Далее, спрашиваю - пользуешься контейнерами из стандартной библиотеки, он отвечает, что не пользуется, внимание!!, у него есть кусок кода с выделением памяти под объекты, который он каждый раз вставляет в код!! Я уже в шоке стою, говорю ему почитай книжки признанных гуру, там написано как надо программировать, он говорит - я так пишу, потому что я должен быть уверен в каждой, написанной мной строчке кода, поэтому он все пишет сам. Ну и в довесок что меня убило, говорит - "это все на вкус и цвет на самом деле, разницы нету, у каждого свой стиль, вот допустим есть две формы для выделения памяти - malloc и new. Я пользуюсь malloc, мне так больше нравится". Говорит, что пишет программы вместе с другом, у них есть какое-то внутреннее соглашение, как надо писать, они его придерживаются Еще у него промелькнуло, что думает еще на счет дальнейшего трудоустройства (он также как и я на 4м курсе, но специальность не связанная с информационными технологиями) - говорит, может программером устроится Я чуть не расплакался ). Собственно программы он пишет для расчетов, связанных с его специальностью.
Короче бывают и такие
static_cast обязателен к использованию, если объекты используют виртуальные функции, потому как именно из-за указателя на таблицу виртуальных функций происходит смещение адреса наследуемого объекта.
Разве? По-моему всегда проходит неявное преобразование. Я, собственно, писал о том, что это неявное преобразование делает static_cast, а не reinterpret_cast. Может, просто выразился туманно.
kexman писал(а):
Единственное что мне в нем не нравится - это то, что в разных функциях (в других частях программы), которые используют эти объекты, приходится в качестве параметров писать GraphicsModelItem<QGraphicsItem> (QGraphicsItem - базовый библиотечный класс иерархии объектов). А это - каждый раз инстанцирование шаблонов, что мне не очень нравится. Попытался заменить в параметрах функций GraphicsModelItem<QGraphicsItem> на TObject, и приводить потом где надо к QGraphicsItem - не получилось.
Хм, а typedef не судьба сделать? Добавлено спустя 3 минуты, 42 секунды kexman К сожалению, такими программистами написано процентов, наверное, 90 от всего когда-либо созданного кода... Так что твой товарищ не одинок.
Member
Статус: Не в сети Регистрация: 12.12.2003 Откуда: Уфа
Билли Бонс Нет ну блин, я скорее всего не буду программистом по профессии, потому что реально оцениваю свои силы Но все равно, хоть это и хобби, стараюсь делать все не абы как. Неужели сложно читать книжки и советоваться с людьми??
Member
Статус: Не в сети Регистрация: 14.01.2004 Откуда: Киев, Украина
Билли Бонс писал(а):
Я, собственно, писал о том, что это неявное преобразование делает static_cast, а не reinterpret_cast. Может, просто выразился туманно.
Да, тут прав, не понял изначально. Добавлено спустя 2 минуты, 29 секунд
kexman писал(а):
я скорее всего не буду программистом по профессии, потому что реально оцениваю свои силы
Ты лучше смотри, по какой специальности больше платят, туда и иди Добавлено спустя 7 минут, 45 секунд Кстати, насчет static_cast, кто скажет, какие в этом коде недостатки:
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения