Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.69/13: Рейтинг темы: голосов - 13, средняя оценка - 4.69
184 / 24 / 4
Регистрация: 18.01.2011
Сообщений: 359

Полиморфизм и шаблонный контейнер.

20.12.2011, 10:57. Показов 2690. Ответов 19
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Как вы знаете, template определяет класс или несколько классов, к которым приводятся ф-и или др. класы использующие template.
Обычно template используют для создания стеков или массивов объектов.
Вопрос вот в чем. Есть у меня объект. и у него несколько наследников. как я могу, указав базовый класс, содержать в стеке с помощью template эти объекты наследники? Дело в том, что обычно наследники "урезаются" до параметров базового класса в template. Можно ли это обойти и как?
За ранее спасибо!
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
20.12.2011, 10:57
Ответы с готовыми решениями:

Шаблонный класс - контейнер С++
Объясните пожалуйста что должна делать данная программа: Создать шаблонный класс-контейнер Array, который представляет собой массив,...

Ассоциативный контейнер и шаблонный класс
Помогите пожалуйста исправить и дополнить код. Задание: Автоматизированная информационная система на железнодорожном вокзале содержит...

Полиморфизм, класс-контейнер
Доброго времени суток. Есть базовый класс и три наследника. Необходимо создать класс-контейнер, владеющий динамическим списком объектов,...

19
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
20.12.2011, 11:00
Вы о полиморфизме слышали?
1
184 / 24 / 4
Регистрация: 18.01.2011
Сообщений: 359
20.12.2011, 11:19  [ТС]
слышали. У меня в классах есть ф-я
C++
1
virtual void Print()
которая
должна перегружаться в каждой мм...в каждом объекте наследнике.
Примерно подобным образом должна работать на мой взгляд программа:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Point Po(1,1);  //просто точка имеет 2 координаты
Pixel Pi(2,3);   //писксел кромее коорд. еще и ставит черный цвет по умолчанию.
Pixel Pi2(12,9,Pixel::Color::red);
 
 
Stack<Point> StackPixel;   //Stack типа template
 
StackPixel.AddObject(Po); //AddObject - добавляет объект в стек.
StackPixel.AddObject(Pi);
StackPixel.AddObject(Pi2);
 
 
for (int i=0; i<StackPixel.KolObject; i++)
{
    StackPixel.MyObject[i].Print(); //выводит в консоль коорд. и цвет.
}
т.е. у поинта выводит только координаты
а у писксела должен выводить еще и цвет.
но фишка в том, что когда я помещаю объект в template то все у меня
превращается однозначтно в Point а значит цвет отбрасывается.
Как мне хранить разные объекты потомки????
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
20.12.2011, 11:34
Андрей2011, Указатели хранить как бэ.
Или сцылки
2
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
20.12.2011, 11:36
Надо хранить указатель на базовый класс, а Вы храните не указатель, а экземпляр.
1
184 / 24 / 4
Регистрация: 18.01.2011
Сообщений: 359
20.12.2011, 12:01  [ТС]
Цитата Сообщение от fasked Посмотреть сообщение
Надо хранить указатель на базовый класс, а Вы храните не указатель, а экземпляр.
- ну где хранить? Я храню и то и то. вот например:
C++
1
2
3
4
5
6
7
8
template<class TObject>
Stack<TObject>::Stack()
{ 
    Max=Max_;
    KolObject=0;
    s4=0;
    MyObject = GetMassivObject();
}
- тут MyObject - это объект типа Point. как тут указатели или ссыки делать не знаю.
а вот ф-я добавления объекта:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template<class TObject>
void Stack<TObject>::AddObject(TObject &Object) 
{ 
 
    //сначала нужно занять память.
    if (KolObject>=Max) 
    {   
        Max = Max << 1;                 //увеличим в 2 раза память 
        MyObject = GetMassivObject();   //Создадим массив.
    }
        //далее добавляем объект в массив объектов.
    *MyObject = Object;
    MyObject[KolObject] = Object; //тут вот объект в массив добавляется!!
    KolObject++;
};
тут я ссылку получаю на объект в том числе и типа Pixel
В чем принципиальная ошибка?

а вот сам класс:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template<class TObject>
class Stack
{
public:
    Stack();
//  void AddObject(TObject &Object); 
    void AddObject(TObject &Object); 
    void Clear();
    int KolObject;
    TObject *MyObject,*GetMassivObject();
 
    ~Stack(); 
private:
    TObject *MyObject2,*MyObject3;
    int Max,s4;
};
- Объекты я храню вв иде указателей...
0
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705
20.12.2011, 12:43
А это что такое? Следи за мыслью:
C++
1
MyObject = GetMassivObject();   //Создадим массив.
То есть я так понял, MyObject указывает на массив нужного размера элементов типа MyObject;

Дальше:
C++
1
2
       *MyObject = Object;
        MyObject[KolObject] = Object; //тут вот объект в массив добавляется!!
В этот массив ты кладёшь объект Object 2 раза: по нулевому смещению
(относительно начала массива) и по смещению KolObject (тоже относительно начала массива)
То есть по окончании этих инструкций у тебя в массиве MyObject лежат 2 объекта Object;
оно так задумано или это ошибка?
1
184 / 24 / 4
Регистрация: 18.01.2011
Сообщений: 359
20.12.2011, 12:59  [ТС]
Да путано получилось. Написал мини прогу в которой отражается моя проблема. Надеюсь на ваше терпение, уважаемые коллеги. Итак:
h файл:
//т.е. создается класс
C++
1
2
3
4
5
6
7
8
9
10
11
12
//**********************************
template<class TObject>
class NewStack
{
public:
    NewStack(TObject &MyObject) :MyObject_(MyObject) {};
    int KolObject;
    TObject MyObject_;
 
    ~NewStack() {}; 
};
//**********************************
сpp. файл (главный. типа main)

C++
1
2
3
4
5
6
7
Point Po(1,1);
Pixel Pi(12,9,Pixel::Color::red);
 
NewStack<Point> NewStackPixel(Po);
NewStackPixel.MyObject_.Print();
NewStack<Point> NewStackPixel(Pi);
NewStackPixel.MyObject_.Print(); //вот тут он отрабатывает как поинт. а я хочу чтоб как пиксел
Добавлено через 2 минуты
ну и добавлю для полного понимания что выводит.
C++
1
2
3
4
void Point::Print()const
{
    cout << '(' << x_ << ',' << y_ << ')';
}
и
C++
1
2
3
4
5
void Pixel::Print()const
{
    Point::Print();
    cout << "Pixel: " << c_ << endl;
}
Добавлено через 1 минуту
в классе Point (класс родитель) объявлена как:
C++
1
virtual void Print()const;
0
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705
20.12.2011, 13:17
C++
1
2
NewStack<Point> NewStackPixel(Pi);
NewStackPixel.MyObject_.Print(); //вот тут он отрабатывает как поинт. а я хочу чтоб как пиксел
Я не уверен, но обратил бы внимание на это: Pi ты кладёшь не как Pixel, а именно как
Point, не ошибка?
NewStack<Point> NewStackPixel(Pi);
0
184 / 24 / 4
Регистрация: 18.01.2011
Сообщений: 359
20.12.2011, 13:20  [ТС]
ну Point - родитель. pixel - наследник. я вот и хочу добиться того чтоб под родительским классом можно было хранить ссылки или указатели на наследников. Но чтоб был пиксел! ато у меня все превращается в поинт. Такая штука.
0
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705
20.12.2011, 13:23
А так если написать?
C++
1
NewStack<Pixel> NewStackPixel(Pi);
В противном случае вроде как при передаче в функцию ты ЯВНО урезаешь
наследника до родителя
1
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
20.12.2011, 13:28
Андрей2011, Пример тебе.
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
#include <iostream>
#include <vector>
 
class Object
{
public:
   virtual ~Object()
   {
   }
   virtual void print()
   {
      std::cout << "In base print" << std::endl;
   }
};
 
class Int_Object : public Object
{
public:
   Int_Object(int val):value(val)
   {
   }
   virtual void print()
   {
      std::cout << "In int print: " << value << std::endl;
   }
private:
   int value;
};
 
typedef std::vector<Object*> objects;
 
int main()
{
   objects objs;
   objs.push_back(new Int_Object(5));
   objs.push_back(new Object());
   for (objects::iterator iter = objs.begin(); iter != objs.end(); ++iter)
   {
      (*iter)->print();
   }
   for (objects::iterator iter = objs.begin(); iter != objs.end(); ++iter)
   {
      delete *iter;
   }
}
2
184 / 24 / 4
Регистрация: 18.01.2011
Сообщений: 359
20.12.2011, 14:12  [ТС]
Уважаемый, kravam, если написать NewStack<Pixel> NewStackPixel(Pi); - то все работает как надо, но мне нада чтоб писать NewStack<Point> NewStackPixel(Pi); - иначе бы я тут не сидел.
Уважаемый, ForEveR, решил фактически за меня всю задачу. Несколько необычным способом но тем не менее.
Вобщем всем спасибо. Буду осознавать последний код.
0
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
20.12.2011, 16:51
Цитата Сообщение от Андрей2011 Посмотреть сообщение
Несколько необычным способом но тем не менее.
Это у Вас был необычный способ добиться полиморфического поведения. Здесь все как раз правильно.
В хронологической последовательности было два раза отмечено:
Цитата Сообщение от ForEveR Посмотреть сообщение
Андрей2011, Указатели хранить как бэ.
Цитата Сообщение от fasked Посмотреть сообщение
Надо хранить указатель на базовый класс, а Вы храните не указатель, а экземпляр.
Казалось бы есть надежда:
Цитата Сообщение от Андрей2011 Посмотреть сообщение
ну Point - родитель. pixel - наследник. я вот и хочу добиться того чтоб под родительским классом можно было хранить ссылки или указатели.
А вот что надо использовать указатель:
Цитата Сообщение от ForEveR Посмотреть сообщение
typedef std::vector<Object*> objects;
Вы так и не осознали.
0
184 / 24 / 4
Регистрация: 18.01.2011
Сообщений: 359
21.12.2011, 10:29  [ТС]
Ну тут товарищ вектор использовал ибо! а по другому фиг знает как оно работает. Щас буду разбираться. Если посетит прозрение - выложу достойный вариант решения.
0
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
21.12.2011, 10:30
Цитата Сообщение от Андрей2011 Посмотреть сообщение
Ну тут товарищ вектор использовал ибо! а по другому фиг знает как оно работает
А какая разница-то?
1
263 / 152 / 33
Регистрация: 29.06.2019
Сообщений: 1,538
08.12.2020, 13:59
в свете новых тенденций - с unique_ptr и Variadic Template с std::forward
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
71
72
// https://stackoverflow.com/questions/14235678/c-polymorphic-container-which-can-add-several-objects-at-once
 
#include <iostream>
#include <vector>
#include <memory>
#include <utility> 
 
using namespace std;
 
class Parent
{
public:
   virtual ~Parent() {}
   virtual void print() {
      std::cout << "In Base print" << std::endl;
   }
};
 
class ChildA : public Parent
{
public:
   ChildA(int val, int val2):value(val), value2(val2) {}
   virtual void print() {
      std::cout << "In A print: " << value << ".." << value2 << std::endl;
   }
private:
   int value;
   int value2;
};
 
class ChildB : public Parent
{
public:
   ChildB(int val, int val2):value(val), value2(val2) {}
   virtual void print() {
      std::cout << "In B print: " << value << ".." << value2 << std::endl;
   }
private:
   int value;
   int value2;
};
 
//===================
 
struct VectorCreator
{
  explicit VectorCreator(std::vector<std::unique_ptr<Parent>> &vec)
    : vec_(vec)
  {}
  
    // supports variadic templates
  template <typename Type, typename... ArgType>
  VectorCreator& create(ArgType&&... arg)
  {
    vec_.push_back(std::unique_ptr<Parent>(new Type(std::forward<ArgType>(arg)...)));
    return *this;
  }
 
private:
  std::vector<std::unique_ptr<Parent>> &vec_;
};
 
// ====================
 
int main(int argc, const char *argv[])
{       
    std::vector<std::unique_ptr<Parent>> myvector;
    VectorCreator(myvector).create<ChildA>(1, 2).create<ChildB>(3, 4).create<ChildB>(5, 6);
 
    for(auto& v : myvector) v->print();
    return 0;
}
Добавлено через 4 минуты
P.S.
хотя unique_ptr обёртку всё-таки можно создавать и в наследниках?.. - не знаю, где лучше?.. может, оставить это дело для класса контейнера и норм. ...
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
08.12.2020, 14:39
JeyCi, этой теме уже почти 10 лет. Но в принципе, учитывая её посещаемость может и нужно бы написать. Но.
Отрадно видеть что человек писавший в теме Когда выделять память
Когда выделять память
что память выделять не нужно. И отвечавший озадаченным людям:
Цитата Сообщение от JeyCi Посмотреть сообщение
вы сами с собой разговариваете?...
про то, что с выходом с уровня С на уровень С++, нормальные контейнеры сами нормально скрывают весь хлам - писала выше - вы не перечитываете - пИшите, что не видели, - понятное дело, и я большего не напишу от ненадобности... зачем мне фабрично аллоцировать динамическую память, как ресурс, - так и не убедили... тем более потом возиться с их ptr'ами размазывая это по всей иерархии...
сейчас пишет
C++
1
new Type(std::forward<ArgType>(arg)...)
выделяя память. Однако имело бы смысл не связывать контейнер и конструирование объектов и смарт пойнеторов на них, а написать-таки фабрику. Как говорилось в указанной теме. Паттерн фабричный метод (и потом - строитель, когда придёт время) - в помощь.
C++
1
2
3
4
explicit VectorCreator(std::vector<std::unique_ptr<Parent>> &vec)
  // : vec_(vec)
     : vec_(std::move(vec))
  {}
0
263 / 152 / 33
Регистрация: 29.06.2019
Сообщений: 1,538
09.12.2020, 08:21
Цитата Сообщение от Андрей2011 Посмотреть сообщение
товарищ вектор использовал ибо! а по другому фиг знает как оно работает.
по-другому только если писать свой контейнер - Template... но взять из std, конечно, удобнее - всё уже написано...
P.S.
простейший container template
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
// https://stackoverflow.com/questions/16596422/template-class-with-template-container
 
#include <iostream>
#include <list>
#include <map>
 
using namespace std;
 
template <template <typename...> typename C, typename T>
struct Cont {
    C<T> info;
};
 
int main(void)
{
    Cont<list, int> cont;
 
    cont.info.push_back(3);
    cont.info.push_back(5);
    
    for(auto& v : cont.info)
        cout << v << endl;
 
    return 0;
}

- вместо int помещайте в него указатели на базовый класс - всё по логике выше
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
09.12.2020, 11:46
Андрей2011 и другие участники, эта тема проведена такими корифеями как ForEveR и fasked, что мне в их компании сложно выглядеть прилично. Я не достаточно силён для этого. Но время принесло новые стандарты и я всё же добавлю вот что. Если вам придётся создавать класс с объектами единоличного владения, то пользуйтесь перемещающей семантикой для копирования и копирующей инициализации
Вообще, копировать такой объект, это плохо по самому замыслу. Но если придётся, то это можно так сделать:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
 #include <vector>
 #include <memory>
 #include <iterator>
 #include <algorithm>
using std::cout;
using  std::cin;
using  std::endl;
 
int main() {
    std::vector<std::unique_ptr<int>> up;
    up.emplace_back(new int(1));
    up.emplace_back(new int(2));
 
    std::vector<std::unique_ptr<int>> up1;
    //std::copy(up.begin(), up.end(), std::back_inserter(up1));//eror::use of deleted function...
    std::copy(std::make_move_iterator(up.begin()), std::make_move_iterator(up.end()), std::back_inserter(up1));
        for(const auto &p:up1)
            cout<<*p<<' ';//1 2
return 0;
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
09.12.2020, 11:46
Помогаю со студенческими работами здесь

Создать шаблонный класс-контейнер Array, который представляет собой массив
Создать шаблонный класс-контейнер Array, который представляет собой массив, позволяющий хранить объекты заданного типа. Класс должен...

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

Заменить контейнер vector, использовавшийся для хранения текстовых строк (листинг 2.3), на контейнер list
Здравствуйте форумчане, может кто объяснить как делать это задание и что собственно мы тут вообще делаем. сам листинг 2.3 ниже ...

Шаблонный массив
Здравствуйте, хотелось бы узнать одну вещь. Код оформить не могу тк с телефона. Я завел шаблонный массив размера 10. Заполняю его...

Шаблонный класс
День добрый. Пишу матричный калькулятор на шаблонном классе. Хочу добиться того, чтобы можно было оперировать с матрицами всех численных...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Модель ЗдрввоСохранения 7: больше работников, больше ресурсов.
anaschu 08.04.2026
работников и заданий может быть сколько угодно, но настроено всё так, что используется пока что только 20%
Дальние перспективы сервера - слоя сети с космологическим дизайном интефейса карты и логики.
Hrethgir 07.04.2026
Дальнейшее ближайшее планирование вывело к размышлениям над дальними перспективами. И вот тут может быть даже будут нужны оценки специалистов, так как в дальних перспективах всё может очень сильно. . .
Горе от ума
kumehtar 07.04.2026
Эта мне ментальная установка, что вот прямо сейчас, мол, мне для полного счастья не хватает (нужное вписать), и когда я этого достигну - тогда и полный кайф. Одна из самых сильных ловушек на пути. . . .
Использование значений реквизитов справочника в документе, с определенными условиями и правами
Maks 07.04.2026
1. Контроль срока действия договора Алгоритм из решения ниже реализован на примере нетипового документа "ЗаявкаНаРаботу", разработанного в конфигурации КА2. Задача: уведомлять пользователя, если. . .
Доступность команды формы по условию
Maks 07.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: сделать доступной кнопку (команда формы "ЗавершитьСписание") при. . .
Уведомление о неверно выбранном значении справочника
Maks 06.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "НарядПутевка", разработанного в конфигурации КА2. Задача: уведомлять пользователя, если в документе выбран неверный склад. . .
Установка Qt Creator для C и C++: ставим среду, CMake и MinGW без фреймворка Qt
8Observer8 05.04.2026
Среду разработки Qt Creator можно установить без фреймворка Qt. Есть отдельный репозиторий для этой среды: https:/ / github. com/ qt-creator/ qt-creator, где можно скачать установщик, на вкладке Releases:. . .
AkelPad-скрипты, структуры, и немного лирики..
testuser2 05.04.2026
Такая программа, как AkelPad существует уже давно, и также давно существуют скрипты под нее. Тем не менее, прога живет, периодически что-то не спеша дополняется, улучшается. Что меня в первую очередь. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru