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

Создать объект, который мог бы принимать в себя любой тип данных

10.09.2016, 18:48. Показов 2403. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Object ten = 10;
Object str = "string";
Такая запись обязательна. То есть тип данных должен быть определен в шаблоне конструктора (я так предполагаю).
В общем всё, что мне пришло в голову это создать ссылку на неопределенный тип, но если вывести адрес ссылок то для всех объектов они одинаковы. Значит ли это, что при создании объекта старые данные стираются и записываются в один и тот же адрес?
И ещё, даже если удастся создать ссылки неопределённого типа на значения, которые были переданы в конструктор, как можно их потом вытащить из этих ссылок?

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
#include "stdafx.h"
#include <iostream>
 
using namespace std;
 
 
 
class Object {
private:
    const type_info& type;
public:
    void* ptrValue;
    template <typename T>
    Object(T someValue) : type(typeid(someValue)) {
 
        T* obj = new T;
        *obj = someValue;
 
        ptrValue = &obj;
        cout << ptrValue << endl;
        cout << type.name() << endl;
        }
};
 
int main()
{
    Object ten = 10;
    Object str = "string";
    system("pause");
    return 0;
}
Миниатюры
Создать объект, который мог бы принимать в себя любой тип данных  
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
10.09.2016, 18:48
Ответы с готовыми решениями:

Можно ли в классе принимать любой тип?
class Figure :public AllData { protected: int p1; int p2; public: Figure(int p1=NULL, int p2=NULL):AllData() { ...

Реализовать C++ объект, который предоставил бы возможность менять тип данных во время исполнения
Помогите пожалуйста!!! Задание следующие: Реализовать c++ объект, который предоставил бы возможность менять тип данных во время...

Можно ли создать тип, который бы включал в себя операции сравнения(=, <>, <, >, >=, <=)?
Как описать множество, которые включает такие операции?

10
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
10.09.2016, 20:21
Распространенные ошибки
0
510 / 272 / 60
Регистрация: 14.12.2010
Сообщений: 548
10.09.2016, 22:04
Цитата Сообщение от Bazzzigna Посмотреть сообщение
Object ten = 10;
Object str = "string";
Такая запись обязательна.
От тебя хотят получить реализацию boost::any.
Как пользоваться тут.
Как раз твой случай:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include "stdafx.h"
#include <iostream>
#include <boost/any.hpp>
 
int main()
{
    typedef boost::any Object;
 
    Object ten = 10;
    Object str = "string";
 
    std::cout << ten.type().name() << ": " << boost::any_cast<int>(ten) << std::endl;
    std::cout << str.type().name() << ": " << boost::any_cast<const char*>(str) << std::endl;
 
    system("pause");
    return 0;
}
0
284 / 232 / 114
Регистрация: 07.09.2016
Сообщений: 584
10.09.2016, 22:06
C++
1
2
3
T* obj = new T;
*obj = someValue;
ptrValue = &obj;
ptrValue в результате имеет адрес локальной переменной, которая в стеке.
выглядит странно, т.к. в меине после 27 строки стек должен изменится. но, может на стеке как-то
заранее выделили память в стеке под переменные Object и только потом пошли работать конструкторы.
и еще надо понимать, как вызываются конструкторы, что там в стеке происходит и т.п. короче,
в таком коде адрес локальной пемеренной может вполне законно быть одним и тем же.
если добавить функцию и в ней сделать то же самое, то адрес оказывается уже другой,
т.к. вызов функции изменяет вершину стека:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
void f(int i)
{
  Object str = "string2";
}
 
int main()
{
    Object ten = 10;
    Object str = "string";
    f(0);
    //system("pause");
    return 0;
}
ну и возможно вы хотели, чтобы ptrValue указывал на выделенную память, а не на локальную переменную:
ptrValue = &obj; // уберите &
впрочем, это было объяснение того, почему адреса оказываются одинаковыми. а как сделать то, что изначально было задумано - это уже отдельная история.
1
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
11.09.2016, 13:28
Bazzzigna, если не сильно утруждаться, то можно придумать что-то такое:
Кликните здесь для просмотра всего текста

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <memory>
#include <utility>
#include <typeinfo>
 
class Any
{
    struct Generic
    {
        virtual ~Generic() = default;
 
        virtual void const * restore(std::type_info const &) const = 0;
        virtual void * restore(std::type_info const &) = 0;
        virtual size_t size() const = 0;
    };
 
    template <typename T>
    union Storage
    {
        using type = T;
 
        T value;
 
        explicit Storage(T const & x)
            : value(x)
        { }
        type * get()
        {
            return &value;
        }
        type const * get() const
        {
            return &value;
        }
        size_t size() const
        {
            return 1;
        }
        ~Storage()
        {
            value.~T();
        }
    };
    template <typename T, size_t N>
    union Storage<T [N]>
    {
        using type = T;
 
        T value[N];
 
        explicit Storage(T const (& x)[N])
        {
            std::uninitialized_copy_n(x, N, value);
        }
        type * get()
        {
            return value;
        }
        type const * get() const
        {
            return value;
        }
        size_t size() const
        {
            return N;
        }
        ~Storage()
        {
            size_t n = N;
            while(n-- > 0)
            {
                value[n].~T();
            }
        }
    };
    template <typename T, typename E = typename Storage<T>::type>
    struct Value final : Generic
    {
        Value(T const & x)
            : storage(x)
        { }
 
        void const * restore(std::type_info const & x) const override
        {
            return (typeid(E) == x) ? storage.get() : nullptr;
        }
        void * restore(std::type_info const & x) override
        {
            return (typeid(E) == x) ? storage.get() : nullptr;
        }
        size_t size() const override
        {
            return storage.size();
        }
 
        Storage<T> storage;
    };
 
public:
    template <typename T>
    Any(T && value)
        : m_gen(new Value<
                    typename std::remove_const<
                        typename std::remove_reference<T>::type
                    >::type
                >(std::forward<T>(value)))
    { }
 
    template <typename T>
    T const * get() const
    {
        return static_cast<T const *>(m_gen->restore(typeid(T)));
    }
    template <typename T>
    T * get()
    {
        return static_cast<T *>(m_gen->restore(typeid(T)));
    }
    size_t size() const
    {
        return m_gen->size();
    }
 
private:
    std::unique_ptr<Generic> m_gen;
};
Здесь еще нужны приемлемые конструктор копирования и оператор присваивания, это допишите сами, идиома virtual constructor в помощь.
Онлайн пример: http://rextester.com/BVY44426
6
98 / 81 / 14
Регистрация: 26.07.2013
Сообщений: 594
01.12.2016, 16:44
DrOffset, очень хотелось покопаться в Вашем последнем примере из #5. Но мой компилятор сразу-же
начал ругаться на строку #9 -
C++
1
  virtual ~Generic() = default;
E2088 Bad syntax for pure function definition.

Я так понял, что он не понимает - default. Я компилирую в RAD Studio XE3.
Подскажите пожалуйста, в чем может быть ошибка, чего в моей системе может не хватать ?
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
01.12.2016, 22:05
Цитата Сообщение от Staut Посмотреть сообщение
Подскажите пожалуйста, в чем может быть ошибка, чего в моей системе может не хватать ?
От компилятора нужна поддержка С++11 или выше.
Я уже довольно давно не слежу за продуктами Borland\Embarcadero, но беглый поиск дал информацию о приемлемой поддержке С++11 лишь в версии RAD Studio 10 Seattle.

В принципе можно и пример переделать под С++03, если использовать boost, то будет совсем легко.
1
98 / 81 / 14
Регистрация: 26.07.2013
Сообщений: 594
02.12.2016, 13:54
DrOffset, прошу еще раз прощения за беспокойство. Не могу раскрутить в своем
C++03 вот такую Вашу конструкцию:
C++
1
2
3
4
5
    template <typename T, typename E = typename Storage<T>::type>
    struct  Value final : Generic
    {
                .....
    };
В первой строке компилятор не понимает: E = typename Storage<T>::type а в следующей строке - final.
Подскажите пожалуйста, как это можно представить в моем случае ?
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
02.12.2016, 15:27
Staut, final можно просто убрать.
Сложность заключается в том, что до С++11 в union`ах нельзя было размещать объекты нетривиальных типов. А здесь именно это свойство используется для запрета вызова конструкторов по умолчанию для массива (в случае, если тип в union нетривиальный, нужно самому контролировать порядок создания и уничтожения его объекта - это нам на руку).

В твоем случае нужно будет union заменить на что-то другое. Например на boost::aligned_storage.
Кликните здесь для просмотра всего текста

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#include <iostream>
 
#include <memory>
#include <typeinfo>
 
#include <boost/type_traits.hpp>
 
class Any
{
    struct Generic
    {
        virtual ~Generic() {}
 
        virtual void * restore(std::type_info const &) = 0;
        virtual size_t size() const = 0;
    };
 
    template <typename T>
    struct Storage
    {
        typedef T type;
 
        T value;
        
        explicit Storage(T const & x)
            : value(x)
        { }
        type * get()
        {
            return &value;
        }
        type const * get() const
        {
            return &value;
        }
        size_t size() const
        {
            return 1;
        }
    };
    template <typename T, size_t N>
    struct Storage<T [N]>
    {
        typedef typename boost::aligned_storage<
            sizeof(T), boost::alignment_of<T>::value
        >::type storage_t;
        
        typedef T type;
 
        storage_t value[N];
 
        T * raw()
        {
            return reinterpret_cast<T *>(value);
        }
        T const * raw() const
        {
            return reinterpret_cast<T const *>(value);
        }
        
        explicit Storage(T const (& x)[N])
        {
            std::uninitialized_copy_n(x, N, raw());
        }
        type * get()
        {
            return raw();
        }
        type const * get() const
        {
            return raw();
        }
        size_t size() const
        {
            return N;
        }
        ~Storage()
        {
            size_t n = N;
            while(n-- > 0)
            {
                (raw() + n)->~T();
            }
        }
    };
    template <typename T, typename E = typename Storage<T>::type>
    struct Value : Generic
    {
        Value(T const & x)
            : storage(x)
        { }
 
        void * restore(std::type_info const & x)
        {
            return (typeid(E) == x) ? storage.get() : 0;
        }
        
        size_t size() const override
        {
            return storage.size();
        }
 
        Storage<T> storage;
    };
 
public:
    template <typename T>
    Any(T const & value)
        : m_gen(new Value<
                    typename boost::remove_const<
                        typename boost::remove_reference<T>::type
                    >::type
                >(value))
    {  }
 
    template <typename T>
    T const * get() const
    {
        return static_cast<T const *>(m_gen->restore(typeid(T)));
    }
    template <typename T>
    T * get()
    {
        return static_cast<T *>(m_gen->restore(typeid(T)));
    }
    size_t size() const
    {
        return m_gen->size();
    }
 
private:
    std::auto_ptr<Generic> m_gen;
};
 
class test
{
public:
    test() { puts(__PRETTY_FUNCTION__); }
    test(test const &) { puts(__PRETTY_FUNCTION__); }
    ~test() { puts(__PRETTY_FUNCTION__); }
};
 
int main()
{
    {
        Any s("12345");
        if(char * v = s.get<char>())
            std::cout << "val: " << v << std::endl;
    }
    std::cout << "===\n";
    {
        Any d(std::string("value"));
        if(std::string * v = d.get<std::string>())
            std::cout << "val: " << *v << std::endl;
    }
    std::cout << "===\n";
    {
        Any o( (test()) );
        if(test * v = o.get<test>())
            std::cout << "test exists, size: " << o.size() << '\n';
    }
    std::cout << "===\n";
    {
        test arr[4] = {};
        
        Any a(arr);
        if(test * v = a.get<test>())
            std::cout << "test exists, size: " << a.size() << '\n';
    }
}
http://rextester.com/GGET65167
1
98 / 81 / 14
Регистрация: 26.07.2013
Сообщений: 594
02.12.2016, 16:10
- Огромное спасибо DrOffset, но все равно жалуется на эту строку:
C++
1
2
3
4
    template <typename T, typename E = typename Storage<T>::type>
    struct Value : Generic
    {
        .....
Указывает на пространство после шаблонного параметра - E и дает сообщение: E2270 > expected.
Т.е. он ждет после параметра E - закрывающей угловой скобки. Он в моей маленькой версии C++xx
не понимает выражения: (E = ).
Видимо не судьба ...
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
02.12.2016, 16:46
Цитата Сообщение от Staut Посмотреть сообщение
Видимо не судьба ...
Да ну прям...
Сделай так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    template <typename T>
    struct Value : Generic
    {
        Value(T const & x)
            : storage(x)
        { }
 
        void * restore(std::type_info const & x)
        {
            return (typeid(typename Storage<T>::type) == x) ? storage.get() : 0;
        }
        
        size_t size() const override
        {
            return storage.size();
        }
 
        Storage<T> storage;
    };
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
02.12.2016, 16:46
Помогаю со студенческими работами здесь

Как правильно создать и инициализировать наследника QGraphicsItem, чтоб они мог принимать сигналы QMainWindow?
САБЖ 8-) QGraphicsItem ведь не унаследован от QObject-а, в отличии от QMainWidnow ... Как их подружить ?

Нужен любой тест, который можно переделать под себя
У кого нибудь есть ли готовый тест можете ли скинуть полностью готовый файл? Пробовал сам но ничего не выходит

Описать графический объект, который представляет из себя изображение папки
Нужна программа в Турбо Паскаль.. Если не трудно с комментариями. Пожалуйста)

Как реализовать метод, который превратит любой объект в byte[] ?
public static byte GetByte(object obj) { byte ret=null; //---------------------------Вот что делать с объектом? ...

Как сделать тип данных или уже есть такой тип данных который состоит из всех печатыемых символов?
Как сделать тип данных или уже есть такой тип данных который состоит из всех печатыемых символов? Если есть то как он называется ?


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru