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

Реализация полиморфного контейнера

18.07.2021, 14:48. Показов 2683. Ответов 15

Студворк — интернет-сервис помощи студентам
Помогите реализовать контейнер для задачи. Условие: контейнер должен быть полиморфным.
задача выглядит следующим образом:

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
#include <iostream>
#include <string>
#include <memory>
 
 
class Figure
{
public:
   Figure() {}
   virtual int size() = 0;
};
 
class Rhombus : public Figure
{
private:
   int number;
 
public:
   Rhombus(int number) { this->number = number; }
   int size() { return this->number; }
};
 
class Triangle : public Figure
{
private:
   int number;
 
public:
   Triangle(int number) { this->number = number; }
   int size() { return this->number; }
};
 
class Octagon : public Figure
{
private:
   int number;
 
public:
   Octagon(int number) { this->number = number; }
   int size() { return this->number; }
};
 
class Oval : public Figure
{
private:
   int number;
 
public:
   Oval(int number) { this->number = number; }
   int size() { return this->number; }
};
 
void number_nodes(std::unique_ptr<Figure> temp)
{
   std::cout << "number : " <<temp->size() << std::endl;
}
 
int main() {
    std::unique_ptr<Figure> t = std::make_unique<Triangle>(3);
    std::unique_ptr<Figure> oc = std::make_unique<Octagon>(8);
    std::unique_ptr<Figure> r = std::make_unique<Rhombus>(4);
    std::unique_ptr<Figure> ov = std::make_unique<Oval>(1);
    number_nodes(std::move(t));
    number_nodes(std::move(oc));
    number_nodes(std::move(r));
    number_nodes(std::move(ov));
    return 0;
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
18.07.2021, 14:48
Ответы с готовыми решениями:

Реализация контейнера unordered_map
Привет. Не могу найти реализацию этого контейнера. Помогите ссылкой или кодом.

Реализация контейнера типа мультимножество
Подскажите пожалуйста: как реализовать контейнер типа &quot;мультимножество&quot;, без использования STL?

Реализация контейнера по типу map
Необходимо создать пользовательский класс по типу map, для реализации &quot;словаря&quot;. Можете помочь с реализацией или подсказать, где...

15
 Аватар для Super-Hacker
342 / 114 / 37
Регистрация: 26.11.2019
Сообщений: 735
18.07.2021, 17:18
Цитата Сообщение от Bobolink Посмотреть сообщение
std::unique_ptr<Figure> t = std::make_unique<Triangle>(3);
std::unique_ptr<Figure> oc = std::make_unique<Octagon>(8);
std::unique_ptr<Figure> r = std::make_unique<Rhombus>(4);
std::unique_ptr<Figure> ov = std::make_unique<Oval>(1);
number_nodes(std::move(t));
number_nodes(std::move(oc));
number_nodes(std::move(r));
number_nodes(std::move(ov));
Что за убийственный стиль?
Ссылочки, ссылочки, не забывайте про них, зачем сразу убивать поинтеры одной функцией

Добавлено через 1 минуту
Цитата Сообщение от Bobolink Посмотреть сообщение
контейнер должен быть полиморфным
Это всё? Ну так их куча в стандартной бибе. Есть что-то более подробное про стиль работы?
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
19.07.2021, 00:59
Цитата Сообщение от Super-Hacker Посмотреть сообщение
контейнер должен быть полиморфным
Цитата Сообщение от Super-Hacker Посмотреть сообщение
Ну так их куча в стандартной бибе.
назови хотя бы один.
0
 Аватар для Super-Hacker
342 / 114 / 37
Регистрация: 26.11.2019
Сообщений: 735
19.07.2021, 14:00
То есть от того, что вместо такой записи
C++
1
std::vector<std::shared_ptr<Figure>>
Написать так (ну или ряльно с нуля написать контейнерчик)
C++
1
2
3
4
template<typename T>
class super_polymorphic_vector : public std::vector<std::shared_ptr<T>>
{
}
Что-то изменится

Вот только профита в таком мало

Проще сделать какой-нибудь враппер с поинтером внутри и писать уже так
C++
1
2
3
std::vector<virtual_wrapper<Figure>> v{};
v.push_back(Oval{12}); // что в принципе лучше заменить на emplace_back
v.push_back(Triangle{2});
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
19.07.2021, 18:53
Цитата Сообщение от Super-Hacker Посмотреть сообщение
class super_polymorphic_vector : public std::vector<std::shared_ptr<T>>
стандартные контейнеры не являются полиморфными.
и если ты унаследуешься от стандартного контейнера,
то от этого никакой полиморфизм по волшебству не появится.

поскольку std::vector не является полиморфным,
то его в любом случае не получится использовать в качестве интерфейса.

если ты сделаешь вот так:

C++
1
2
3
using interface_t = std::vector<std::shared_ptr<T>>;
interface_t* p = new super_polymorphic_vector ;
delete p;
то получишь UB
0
Заблокирован
19.07.2021, 19:01
Цитата Сообщение от hoggy Посмотреть сообщение
стандартные контейнеры не являются полиморфными
Являются, просто ты ещё этого не проходил, да и вряд ли пройдёшь. Но для табуреток из-за парты вроде тебя есть std::any<> с дин. полиморфизмом.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
19.07.2021, 19:28
Цитата Сообщение от mashmed135 Посмотреть сообщение
Являются
см #3

Добавлено через 3 минуты
Цитата Сообщение от mashmed135 Посмотреть сообщение
Но для табуреток из-за парты вроде тебя есть std::any<> с дин. полиморфизмом.
во-первых, нет никаких:
Цитата Сообщение от mashmed135 Посмотреть сообщение
std::any<>
потому что std::any вообще не является шаблоном.

во-вторых, std::any не является полиморфным контейнером.
у него обычный (не_виртуальный) деструктор
0
 Аватар для Super-Hacker
342 / 114 / 37
Регистрация: 26.11.2019
Сообщений: 735
19.07.2021, 19:54
Да стд ани норм тип. На ифах там можно уйму всего сделать

Цитата Сообщение от hoggy Посмотреть сообщение
using interface_t = std::vector<std::shared_ptr<T>>;
interface_t* p = new super_polymorphic_vector ;
delete p;
ОМГ. Вот так никто и не понял, что же ТС имел в виду.
Интерфейсные контейнеры или контейнеры с хранением интерфейсов
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
19.07.2021, 20:21
Цитата Сообщение от Super-Hacker Посмотреть сообщение
Вот так никто и не понял, что же ТС имел в виду.
что значит "никто" ?
ты за всех то не болтай.

если ты сам лично чего-то не понял,
это не значит, что и другие тоже не поняли.

Цитата Сообщение от Bobolink Посмотреть сообщение
контейнер должен быть полиморфным.
здесь конкретно обозначенно,
что контейнер должен быть полиморфным.

для этого,
у него должны быть полиморфные методы,
сиречь виртуальные функции-члены.
опционально, но крайне важно:
у него должен быть вирт. деструктор.
0
19.07.2021, 20:28

Не по теме:

Цитата Сообщение от hoggy Посмотреть сообщение
стандартные контейнеры не являются полиморфными.
А як жеж статический-то полиморфизм? )

0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
19.07.2021, 20:36
Цитата Сообщение от Croessmah Посмотреть сообщение
А як жеж статический-то полиморфизм?
это ты можешь обсудить с господином mashmed135,
когда будешь сидеть с ним за одной партой.
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
19.07.2021, 20:45
Цитата Сообщение от hoggy Посмотреть сообщение
это ты можешь обсудить с господином mashmed135,
когда будешь сидеть с ним за одной партой.
Ой, точно. На cppreference секция Template based Polymorphism in C++ в состоянии This section is incomplete.
Да, не повезло тебе.
0
 Аватар для Super-Hacker
342 / 114 / 37
Регистрация: 26.11.2019
Сообщений: 735
19.07.2021, 21:13
Цитата Сообщение от Croessmah Посмотреть сообщение
incomplete
variadic
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
20.07.2021, 01:53
Цитата Сообщение от Croessmah Посмотреть сообщение
Да, не повезло тебе.
ты, наверное, не понял:
когда я предложил тебе сеcть за парту с mashmed135,
то я хотел дать тебе понять: мне твои кривляния не интересны.
просто не пиши мне ничего.

-----------------------------

всем остальным:
язык четко регламентирует, какие классы или объекты являются полиморфными

на определении термина "полиморфный класс" базируется стандартная мета-функция is_polymorphic,
которая возвращает true, если параметр T - полиморфный класс.

в документации прямо указывается по какому критерию она должна определять "полиморфность"
If T is a polymorphic class (that is, a non-union class that declares or inherits at least one virtual function), provides the member constant value equal to true. For any other type, value is false.

данная мета-функция была добавлена в стандарт с++11.

но если, допустим, у тебя старый компилятор,
или тебе просто просто любопытно,
как эта функция устроенна внутри,
то ты можешь изготовить её самостоятельно.

для этого нужно просто понять идею:
полиморфный объект - это объект, который внутри себя хранит информацию о своём dynamic type
то есть, если объект полиморфный,
значит помимо собственных данных-членов,
он так же должен хранить внутри себя информацию об RTTI

классическая реализация языка предполагает зашить
в объект "невидимый" указатель на т.н. vtbl - таблицу виртуальных функций.

с помощью vtbl различные typeid и компания вытаскивают все необходимую им информацию
о типе в рантайме.

из всего вышесказанного следует,
что если класс полиморфный,
тогда его размер неизбежно должен увеличиться на размер скрытого указателя на vtbl.
и даже, если там не vtbl, а какая нибудь алтернативно-одарённая вундервафля,
все равно, размер полиморфного объекта неизбежно должен увеличиться
на размер этой вундервафли.

отсюда нехитрое телодвижение:


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
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
 
namespace tools
{
    template<class t> struct is_polymorphic
    {
        struct der: public t
        {
            virtual ~der() = 0;
        };
        enum { value = sizeof(t) == sizeof(der) };
        static_assert(value != 0 || sizeof(t) < sizeof(der), "err");
    };
    
    
} //namespace tools
 
#include <iostream>
#include <type_traits>
 
struct A { int m; };
struct B { virtual void foo(); };
struct C : B {};
struct D { virtual ~D() = default; };
 
#define dSTD(t) std::is_polymorphic<t>::value
#define dTOOLS(t) tools::is_polymorphic<t>::value
 
 
int main()
{
    std::cout << std::boolalpha
          << dSTD(A) << " VS " << dTOOLS(A) << '\n'
          << dSTD(B) << " VS " << dTOOLS(B) << '\n'
          << dSTD(C) << " VS " << dTOOLS(C) << '\n'
          << dSTD(D) << " VS " << dTOOLS(D) << '\n';
}
 
#pragma GCC diagnostic pop
output:
Code
1
2
3
4
false VS 0
true VS 1
true VS 1
true VS 1
в примере выше der - класс "пустышка" (у него нет данных членов)
но при этом у него есть вирт. деструктор,
а значит он - полиморфный.

если t - тоже полиморфный, значит vtbl у него уже есть.
и значит наследник-пустышка уже никак на итоговый размер не повлияет.
то бишь выполняется равенство:
C++
1
sizeof(t) == sizeof(der)

если же t - не_полиморфный класс,
тогда наследник der привносит с собой скрытый указатель на vtbl,
и значит sizeof(der) неизбежно должен быть больше,
чем sizeof(t) как минимум на размер этого самого указателя на vtbl
то бишь выполняется требование:
C++
1
static_assert(value != 0 || sizeof(t) < sizeof(der), "err");
-----

итого:
с точки зрения правил языка с++:
полиморфный класс - классс, у которого есть вирт. функции-члены.
полиморфный объект - экземпляр полиморфного класса.

а вся эта болтовня домохозяек о статическом полиморфизме - это вообще из другой оперы,
и к сабжу никакого отношения не имеет.
1
0 / 0 / 0
Регистрация: 18.07.2021
Сообщений: 3
20.07.2021, 13:01  [ТС]
Препод сказал, что
std::vector<std::shared_ptr<Figure>>
можно использовать, т.к. принимает умный указатель на базовый тип и на всех наследников тоже значит
0
 Аватар для Super-Hacker
342 / 114 / 37
Регистрация: 26.11.2019
Сообщений: 735
20.07.2021, 16:57
Цитата Сообщение от Bobolink Посмотреть сообщение
Препод сказал, что
std::vector<std::shared_ptr<Figure>>
hoggy, спасибо за пояснение

Видимо ТС всё же просто хотел сложить в контейнер наследников интерфейса
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
20.07.2021, 16:57
Помогаю со студенческими работами здесь

Реализация стека наследованием реализации контейнера
Имеется иерархия классов, во главе которой класс-интерфейс. Нужно создать стек для хранения указателей на интерфейс для полиморфной...

Реализация итераторов для собственного контейнера
Все вродебы да работает и даже хорошо, но есть 1 но. На cbegin и cend получаю такой error, и не могу понять как мне привести аргумент...

Реализация примитивного STL совместимого контейнера
Как то застрял на этом. Как правильно объявить все typedef для итератора? Нужен минимальный набросок такого контейнера.template&lt;typename...

Реализация контейнера идентичного std::vector по Страуструпу
При попытке скомпилировать код появляются ошибки, хотя делаю вроде как пишет Бьярне. Компилятор VSE 2010. Код: Содержание...

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


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

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru