Russian Qt Forum
Ноябрь 23, 2024, 19:20 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3 4 ... 6   Вниз
  Печать  
Автор Тема: Шаблоны.  (Прочитано 36777 раз)
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #15 : Март 25, 2012, 20:15 »

Решил шаблоны освоить. Написал шаблон. Шаблон типонезависимый и не знает полей классов Ti и Tp. Описал частично его методы, понял что кое-где гораздо удобней, когда класс знает типы классов Ti и Tp.
 
Решил что нужно от него наследовать класс и в классе переопределять некоторые методы в зависимости от типов.

Мне кажется, или тут правда можно обойтись специализацией шаблона?
Можно, конечно сделать всё и через специализацию, но в таком случае ему придётся реализовывать весь функционал заново..
С другой стороны можно написать базовый класс, функционал которого не зависит от типа шаблона и наследоваться от него с последующей реализацией специализации..
Но опять-таки здесь всё зависит от конкретной задачи..
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #16 : Март 25, 2012, 20:35 »

Можно, конечно сделать всё и через специализацию, но в таком случае ему придётся реализовывать весь функционал заново..
С другой стороны можно написать базовый класс, функционал которого не зависит от типа шаблона и наследоваться от него с последующей реализацией специализации..
Но опять-таки здесь всё зависит от конкретной задачи..
Давайте попробуем конкретизировать. Есть такие простые структурки которые хотим обощить
Код
C++ (Qt)
struct Point3D  { double x, y, z; };
struct Point3F  { float x, y, z; };
struct Point3W { float x, y, z, w; };
 
Конечно мы можем писать напр
Код
C++ (Qt)
std::vector <Point3D> vec1;
std::vector <Point3F> vec2;
и.т.д.
 
Но так мы очень быстро окажемся заваленными ф-циями/методами которые отличаются только типом вектора. И тогда придется делать еще template. Вместо этого мы хотим сделать "нормальный" базовый класс, его потомки уже будут template, а мы будем работать с базовым.

Как это сделать?
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #17 : Март 25, 2012, 20:57 »

Можно, конечно сделать всё и через специализацию, но в таком случае ему придётся реализовывать весь функционал заново..
С другой стороны можно написать базовый класс, функционал которого не зависит от типа шаблона и наследоваться от него с последующей реализацией специализации..
Но опять-таки здесь всё зависит от конкретной задачи..
Давайте попробуем конкретизировать. Есть такие простые структурки которые хотим обощить
Код
C++ (Qt)
struct Point3D  { double x, y, z; };
struct Point3F  { float x, y, z; };
struct Point3W { float x, y, z, w; };
 
Конечно мы можем писать напр
Код
C++ (Qt)
std::vector <Point3D> vec1;
std::vector <Point3F> vec2;
и.т.д.
 
Но так мы очень быстро окажемся заваленными ф-циями/методами которые отличаются только типом вектора. И тогда придется делать еще template. Вместо этого мы хотим сделать "нормальный" базовый класс, его потомки уже будут template, а мы будем работать с базовым.

Как это сделать?

Не совсем понял, что мешает сделать класс Point шаблонным и все функции, связанные с математикой над этим классом так же шаблонными?
В данном случае нормальный базовый клас если и можно будет сделать, то только пустым..
Код
C++ (Qt)
struct base_point {
virtual ~base_point() {}
};
 
template <class T>
struct point : public base_point
{
   T x, y, z;
};
 
list<base_point*> list_of_points;
 
   
Но смысл в этом?
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #18 : Март 25, 2012, 21:16 »

Я говорю о базовом классе контейнере, разные наследники которого будут хранить разные типы элементов.

Обобщать сами структуры - для простоты положим что это не нужно, в конце-концов результатом обобщения будут разные классы, и задача с контейнером никак не упрощается

Edit: m_ax, просьба: цитированием не злоупотребляйте, а то длинная портянка получается  Улыбающийся
« Последнее редактирование: Март 25, 2012, 21:18 от Igors » Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #19 : Март 25, 2012, 21:22 »

Я говорю о базовом классе контейнере, разные наследники которого будут хранить разные типы элементов.

Обобщать сами структуры - для простоты положим что это не нужно, в конце-концов результатом обобщения будут разные классы, и задача с контейнером никак не упрощается

Edit: m_ax, просьба: цитированием не злоупотребляйте, а то длинная портянка получается  Улыбающийся
Всё равно не понял, чем мотивировано такое поведение? Чем это отличается, скажем от простого typedef?
Код
C++ (Qt)
typedef vector<PointF> vector_of_pointsf;
typedef vector<PointD> vector_of_pointsd;
...
 
В чём Вы видите выйгрыш от вашей задумки (я не совсем понимаю какого поведения Вы хотите добиться)?
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #20 : Март 25, 2012, 21:34 »

В чём Вы видите выйгрыш от вашей задумки (я не совсем понимаю какого поведения Вы хотите добиться)?
С точки зрения использования
Код
C++ (Qt)
class CModel {
...
CoordVec * mCoord; // или CoordVec & mCoord;
};
 
CoordVec - базовый класс (контейнер), возможно абстрактный. Конкретный потомок может хранить Point в разных форматах, но делать template для CModel мне утомительно и нежелательно
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #21 : Март 25, 2012, 21:53 »

Ну если CoordVec может быть абстрактным, то можно сделать так (хотя это сомнительное решение, имхо)
Код
C++ (Qt)
enum typeOfCoordVector { VectorPointF, VectorPointD};
 
struct base_coord_vec
{
   virtual ~base_coord_vec() {}
   virtual type_coord_vec() const = 0;
};
 
struct coord_vec_d : public base_coord_vec
{
   typedef std::vector<PointD> vector_type;
   vector_type vector;
   virtual type_coord_vec() const { return VectorPointD; }
};
 
struct coord_vec_f : public base_coord_vec
{
   typedef std::vector<PointF> vector_type;
   vector_type vector;
   virtual type_coord_vec() const { return VectorPointF; }
};
 
class CModel {
   base_coord_vec *mCoord;
};
 

Если я правильно уловил суть. Ещё можно написать свой класс variant и создавать вектор
Код
C++ (Qt)
vector<variant>
 
А variant может быть чем угодно.. Ну типа аналог QVariant..
 Непонимающий
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #22 : Март 25, 2012, 22:12 »

Да, template вещь полезная, но "выносит моск" капитально  Улыбающийся Давайте я еще раз попробую объяснить откуда "берется необходимость". Простейшее решение
Код
C++ (Qt)
template <class T>
class CModel {
...
vector <T> mCoord;
};
 
Да, так все будет работать, НО template "проникает наверх". То есть везде где я использую CModel (а таких мест масса) я обязан буду "специфицироваться", объявить template во всех ф-циях и методах которые принимают/возвращают CModel. Это очень неудобно, т.к. у CModel есть множество др дел кроме mCoord, Если же я хочу сделать CModel членом др класса - еще хуже.

Поэтому естественно желание "замкнуть" template в классе контейнера чтобы оно не лезло во все щели  
 
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #23 : Март 25, 2012, 22:26 »

Тогда логично написать свой класс variant (есть уже готовые реализации), объявит
Код
C++ (Qt)
typedef std::vector<variant> super_vector;
 

А в variant  уже записывать хоть PointF, хоть PointD, да и всё что душа пожелает)
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #24 : Март 25, 2012, 22:48 »

А в variant  уже записывать хоть PointF, хоть PointD, да и всё что душа пожелает)
Это в данном случае не годится: Point xx - низкоуровневые POD структуры, никакие "обертки" недопустимы с точки зрения доп расходов по памяти и конвертации

А чем Вам не нравится template класс с non-template базовым ?
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #25 : Март 25, 2012, 23:02 »

Цитировать
А чем Вам не нравится template класс с non-template базовым ?
А как вы себе его представляете?
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #26 : Март 25, 2012, 23:15 »

А как вы себе его представляете?
Код
C++ (Qt)
struct CoordVec {
virtual size_t size( void ) const = 0;
virtual Point3D & Get3D( size_t index ) = 0;
virtual Point3F & Get3F( size_t index ) = 0;
virtual Point3W & Get3W( size_t index ) = 0;
 // то же для Set и.т.д
};
 
template <class T>
struct CoordVecT : public CoordVec {
virtual size_t size( void ) const { return mData.size(); }
..
vector <T> mData;
};
 
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #27 : Март 25, 2012, 23:25 »

Ну можно и так. Я бы ещё в базовый класс добавил виртуальную функцию
Код
C++ (Qt)
virtual typeOfVector type() const = 0;
 
Чтоб можно было сразу определить с чем имеем дело.
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #28 : Март 25, 2012, 23:31 »

А как теперь реализовать такую ф-цию (ну или метод) не городя switch(ей)
Код
C++ (Qt)
void Append( CoordVec & dst, const CoordVec & src );
 
?
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #29 : Март 25, 2012, 23:47 »

Поскольку в базовом классе CoordVec нет никакого вектора, то во-первых придётся использовать либо dynamic_cast, либо static_cast если известно к чему приводить..
И так вы не избавитесь от switch или ему подобных проверок и т.д. В этом плане этот вариант, конечно проигрывает..
Да и вызов виртуальных функций - тож дороговато( (а если учесть, что это чтение/запись)
   
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Страниц: 1 [2] 3 4 ... 6   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.337 секунд. Запросов: 23.