Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Tankist 90
0 / 0 / 0
Регистрация: 27.04.2015
Сообщений: 248
#1

Параметр шаблона класса как собственный тип данных - C++

29.04.2017, 00:14. Просмотров 357. Ответов 21
Метки нет (Все метки)

Приветствую. Такой вопрос: как перегрузить операторы класса-шаблона, где в качестве аргумента шаблона выступает собственный тип данных. Если приведёте примеры кода - буду премного благодарен.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.04.2017, 00:14
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Параметр шаблона класса как собственный тип данных (C++):

Как ограничить тип данных шаблона класса? - C++
Решил создать два класса: умный массив и его менеджер. Так как массив может хранить любые типы, то его сделал шаблоном: template <class...

Свой тип как параметр шаблона - C++
Есть вопрос по коду: #include <iostream> #include <memory> #include <vector> using namespace std; template<class T> class...

Как ограничить параметр типа шаблона только числовыми типами данных? - C++
Собствено, сабж. Ключевое для поиска слово хотябы.

Как узнать тип данных шаблона функции? - C++
Я старался делать так: #include<iostream> #include<fstream> #include<conio.h> #include<stdlib.h> #include<string> using namespace...

Как сделать функцию, которая тип данных использует как параметр? - C++
Хочу сделать функцию function("переменные", "тип данных"). Можно ли это реализовать? А именно, более подробно что-то в этом роде: ...

Собственный тип данных в deque - C++
Добрый день. Возникла проблема. Надо очистить объект и вписать значения. obj.clear() не работает, как я понимаю он вызывает функцию из...

21
GoldenId
Нарушитель
130 / 128 / 32
Регистрация: 11.11.2010
Сообщений: 733
Записей в блоге: 13
Завершенные тесты: 1
29.04.2017, 00:20 #2
std::greater
Оно?
0
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
6911 / 3188 / 315
Регистрация: 04.12.2011
Сообщений: 8,823
Записей в блоге: 5
29.04.2017, 01:30 #3
Цитата Сообщение от Tankist 90 Посмотреть сообщение
как перегрузить операторы класса-шаблона, где в качестве аргумента шаблона выступает собственный тип данных.
Перегрузка операций для шаблона это вещь бессмысленная. Шаблон должен использовать операции которые нужны для реализации его алгоритмов. А операции, должны быть перегружены у типов которые передаются шаблону. Разумеется, они должны быть перегружены в соответствии с семантикой шаблона, иначе их туда лучше не передавать.
0
Tankist 90
0 / 0 / 0
Регистрация: 27.04.2015
Сообщений: 248
29.04.2017, 11:42  [ТС] #4
Цитата Сообщение от IGPIGP Посмотреть сообщение
операции, должны быть перегружены у типов которые передаются шаблону
Т.е. если я передаю в шаблон класса параметр являющийся новым типом данных, я должен перегрузить все использующиеся в классе-шаблоне операторы в теле передаваемого класса?
0
Croessmah
Пришел
Эксперт CЭксперт С++
13759 / 7839 / 893
Регистрация: 27.09.2012
Сообщений: 19,237
Записей в блоге: 3
Завершенные тесты: 1
29.04.2017, 11:45 #5
Tankist 90, если честно, не очень понятно что Вы имеете ввиду.

C++
1
2
3
4
5
6
7
8
9
10
template<typename T>
class Some
{
//...
public:
   Some operator+(const Some &rhv)
   {
      //...
   }
};
1
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
6911 / 3188 / 315
Регистрация: 04.12.2011
Сообщений: 8,823
Записей в блоге: 5
29.04.2017, 11:57 #6
Цитата Сообщение от Tankist 90 Посмотреть сообщение
я должен перегрузить все использующиеся в классе-шаблоне операторы в теле передаваемого класса?
иначе получите ошибку компиляции когда попробуете инстанцировать. Покажите кусочек кода, поскольку есть неоднозначность в Вашем вопросе. Посмотрите вопрос Croessmah. Он намекает на то, что и шаблон может перегрузить операции. Причём пользовательсий (или не пользовательский) тип - параметр шаблона, строго говоря, может и не перегружать ничего подобного. В этом случае семантика, как правило, не будет соблюдаться, но формально это реализуемо. Например, при сложении заставить пользовательский тип спеть Соловья Алябьева вместо сложения. Если он умеет конечно.
Если пользовательский тип имеет метод вроде T add(const &T, const T&) например, то можно и неперегружая + в T сохранить семантику при перегрузке + в шаблоне. Хотя изврат наверное. Покажите, что Вы имеете ввиду.
0
Tankist 90
0 / 0 / 0
Регистрация: 27.04.2015
Сообщений: 248
29.04.2017, 12:06  [ТС] #7
Цитата Сообщение от IGPIGP Посмотреть сообщение
Покажите кусочек кода
Шаблонный класс:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
template <class T>
class Set
{
 
  int g; //переменная для хранения размерности
  T *mas;// для создания массива
 
public:
 
    Set(){}//конст. без парам.
 
    Set(int a)// с параметром
    {
        g=a;
 
        mas=new T[g];// создаём массив
        for(int i=0;i<g;i++)// заполнием нулями
        {
           mas[i]=0;
        }
    }
 
    Set(Set&ob){}// конст. копирования
    
 
    void set()// функц. заполнения массива из консоли
    {
      cout<<"Введите массив:\n";
      for(int i=0;i<g;i++)// заполняем
      {
        cin>>mas[i];
      }
    }
//----------------------------------------//
    Set operator* (Set <T>& ob)// перегрузка для *
    {
      Set <T> t(g);
      int k=0;
 
      for(int i=0;i<g;i++)
      {
          for(int j=0;j<g;j++)
          {
            if(mas[i]==ob.mas[j])//если массивы равны...
            {
              t.mas[k++]=mas[i];//... записать в новый
              break;
            }
          }
      }
      if(k!=0){
          for(int i=0;i<k;i++)
              cout<<"\nсовпадениe  обнаружено:"<<t.mas[i]<<endl;
      }else cout<<"\nсовпадений не обнаружено..."<<endl; 
 
        return t;
    }
friend istream& operator>>(istream &s, T ob )//перегрузка для >>
{ 
    s>>ob;
    return s;
}
 
friend ostream& operator<<(ostream &s, T ob)//перегрузка для <<
{
    s<<ob;
  return s;
}
 
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
class e//собственный тип передав. в кач. парам. шаблона
{
public:
   e& operator=(int a)//перегрузка для =
   {
     // что-то пишем 
   }
 
  const bool& operator==(e& ob)//перегрузка для ==
   {
      // что-то пишем
   }
};
0
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
6911 / 3188 / 315
Регистрация: 04.12.2011
Сообщений: 8,823
Записей в блоге: 5
29.04.2017, 12:13 #8
Цитата Сообщение от Tankist 90 Посмотреть сообщение
Set(Set&ob){}// конст. копирования
Это плохо! Нужно бы выделить в копии память так как это делает конструктор с целым параметром и потом скопировать туда элементы. Иначе первая же перадача в функцию завалит программу. И параметр по конст ссылке передайте.
Что касается перегрузки операторов для шаблона<Т> то она должна бы быть тут наименее зависима от возможностей T.
0
Tankist 90
0 / 0 / 0
Регистрация: 27.04.2015
Сообщений: 248
29.04.2017, 12:47  [ТС] #9
Цитата Сообщение от IGPIGP Посмотреть сообщение
Нужно бы выделить в копии память так как это делает конструктор с целым параметром и потом скопировать туда элементы
Можно на примере? Просто мы почти не работали с конструкторами копирования. Просто пишем их как элемент класса и всё...

Добавлено через 28 минут
Вы имели в виду что-то вроде этого:
C++
1
2
3
4
5
6
7
8
Set(const Set&ob)
{
  mas=new T[ob.g];// создаём массив
        for(int i=0;i<ob.g;i++)// заполняем нулями
        {
           mas[i]=0;
        } 
}
0
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
6911 / 3188 / 315
Регистрация: 04.12.2011
Сообщений: 8,823
Записей в блоге: 5
29.04.2017, 13:19 #10
Цитата Сообщение от Tankist 90 Посмотреть сообщение
Вы имели в виду что-то вроде этого:
Да. Только размер получаете у оригинала, потом копируете не нули а соответственно элементы.
Что касается операторов, то можно как угодно, но я считаю, что потребность диктует клиент. Пусть клиентами шаблона являются числовые типы : int, /...и пр. int/, float, double, long double и Вы делаете класс для работы с векторами (мат) на этих типах. То есть Вам нужно складывать, считать векторное и скалярное произведения и пр. Тогда Вам не нужно реализовывать операции на типах клиентах. Они уже есть. А операция сложения на типе - шаблоне будет пользоваться операциями для типов - параметров (клиентов). Хотя если говорить только о этой операции, то передача параметром типа string не вызовет ошибки, хотя семантически будет не верной. Но если вы создали шаблон для сцепления строк, то бессмысленно будет передавать числовые типы. В C++ Bы не можете конкретизировать тип предложением вроде were T is int, float, double и имеет смысл перегружать операторы вроде сложения в контексте потребностей клиента. Наделять клиента такой способностью лишь для дальнейшей перегрузки в шаблоне бессмысленно. Потребность должна диктоваться от Вашего пользовательского класса. В принципе таких классов нужно бы иметь группу либо такой класс должен поддерживать семантику для группы уже существующих типов. Иначе зачем шаблон? Какие типы он будет обобщать?

Добавлено через 8 минут
Цитата Сообщение от IGPIGP Посмотреть сообщение
Что касается перегрузки операторов для шаблона<Т> то она должна бы быть тут наименее зависима от возможностей T.
Это полностью противоречит сказанному выше. Но это потому, что как я понял тогда Ваш Set - аналог множества и не имеет ничего общего с мат операциями над своим типом. То есть, вообще то о чём Вы спрашиваете зависит от того что Вы намерены сделать.
0
Tankist 90
0 / 0 / 0
Регистрация: 27.04.2015
Сообщений: 248
29.04.2017, 13:40  [ТС] #11
C++
1
2
3
4
5
6
7
8
Set(const Set&ob)
{
  mas=new T[ob.g];// создаём массив
        for(int i=0;i<ob.g;i++)
        {
           mas[i]=ob.mas[i]; //?
        } 
}
Собственно, вот задание:
1. Создать шаблон заданного класса. Определить конструкторы, деструктор, перегруженную операцию присваивания
(“=”) и операции, заданные в варианте задания.
2. Написать программу тестирования, в которой проверяется использование шаблона для стандартных типов данных.
3. Выполнить тестирование.

Первых три пункта я выполнил давно и они работали прекрасно. А вот далее и возникли проблемы:

4. Определить пользовательский класс, который будет использоваться в качестве параметра шаблона. Определить в классе необходимые функции и перегруженные операции.
5. Написать программу тестирования, в которой проверяется использование шаблона для пользовательского типа.
6. Выполнить тестирование.
0
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
6911 / 3188 / 315
Регистрация: 04.12.2011
Сообщений: 8,823
Записей в блоге: 5
29.04.2017, 16:11 #12
Tankist 90, теперь конструктор копии адекватен. В деструкторе не забудьте delete [] mass;
оператор присваивания должен возвращать ссылку (на себя *this). Сначала проверяем this==&obj и если да то уходим. Иначе проверяем g==obj.j если да то просто копируем из объекта g элементов (все то есть). если нет, то освобождаем память по указателю и выделяем и копируем по новой. Эта часть аналогична той что в конструкторе копии и поэтому имеет смыл написать отдельный метод вроде того что:
C++
1
2
3
4
5
6
7
void init (const Set&ob) {
mas=new T[obj.g]; 
        for(int i=0;i<ob.g;i++)
        {
           mas[i]=ob.mas[i]; //?
        } 
}
и вызывать его как в конструктор, так и в оператор =
0
Croessmah
Пришел
Эксперт CЭксперт С++
13759 / 7839 / 893
Регистрация: 27.09.2012
Сообщений: 19,237
Записей в блоге: 3
Завершенные тесты: 1
29.04.2017, 16:17 #13
IGPIGP, не совсем корректен. g забыли скопировать.
1
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
6911 / 3188 / 315
Регистрация: 04.12.2011
Сообщений: 8,823
Записей в блоге: 5
29.04.2017, 17:44 #14
Цитата Сообщение от Croessmah Посмотреть сообщение
IGPIGP, не совсем корректен. g забыли скопировать.
Где? Я написал что если g равны то просто копируем g элементов, а если нет то удаляем и делаем снова как в конструкторе копии. А там g копируется. Хотя это тоже можно бы в предложенный init интегрировать.
Но в конструкторе копии нет ничего вроде g=obj.g это да.
0
Tankist 90
0 / 0 / 0
Регистрация: 27.04.2015
Сообщений: 248
30.04.2017, 15:38  [ТС] #15
Цитата Сообщение от IGPIGP Посмотреть сообщение
оператор присваивания
Можете на примере показать, как правильно перегрузить operator= в моём случае?
0
30.04.2017, 15:38
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
30.04.2017, 15:38
Привет! Вот еще темы с ответами:

Как передать параметр в собственный манипулятор с параметром? - C++
Ребята, вопрос, вот задача: Создать манипулятор endp(n), задающим условие перехода на новую страницу: если счетчик строк в ...

Как создать свой собственный тип на C++? - C++
Здравствуйте!!! Возник вопрос как создать свой собственный тип на С++ который включат такие типы как int, string, double?

Передача функции как параметр шаблона - C++
Хочу передавать в шаблон любую функцию без параметров и вызывать ее из него. Как это сделать? Не работает, но примерно так должно...

Зачем нужен шаблон как параметр шаблона? - C++
Видел много примеров, но что-то не особо понятно зачем и как это работает.


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru