0 / 0 / 0
Регистрация: 12.04.2016
Сообщений: 75
1

Указатель типа void. Использование косвенного связывания через универсальный указатель

20.11.2018, 22:30. Показов 2005. Ответов 3

Студворк — интернет-сервис помощи студентам
Необходимо использовать косвенного связывания через универсальный указатель, примерный вид:
struct обобщение{ключ; void* на что угодно} // железное условие

подвиснув пришла к такому решению:
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
struct LangProg  // как раз обобщение
{
    enum key { PROCEDURN = 1, OBOR } key; // по ключу определяем тип
    void* spec;
};
 
void readPr(bool &Procedurn, ifstream &ifst)
{
    ifst >> Procedurn; // c текста считываем bool переменную 
}
 
LangProg* InLangP(ifstream &ifst) 
{
    LangProg *kont = new LangProg;
    int prov;
    ifst >> prov;
    switch (prov)
    {
    case 1:
        kont->key = LangProg::key::PROCEDURN;
        readPr(*static_cast<bool*>(kont->spec), ifst);
        return kont;
    case 2:
        kont->key = LangProg::key::OBOR;
        readObOr(*static_cast<ObOr*>(kont->spec), ifst);
        return kont;
    default:    // нет совпадений -> нет записи
        exit;
    }
}
ну и ошибка в функции readPr тк судя по всему он не понимает что это тип bool
а как ему доходчиво объяснить? *(bool*)(kont->spec) тоже не вариант
в тексте только 0 и 1

и такой вариант не катит

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
void readPr(void* Procedurn, ifstream &ifst)
{
    bool gl;
    ifst >> gl;
    *static_cast<bool*>(Procedurn) = gl;
}
 
LangProg* InLangP(ifstream &ifst)   
{
    LangProg *kont = new LangProg;
    int prov;
    ifst >> prov;
    switch (prov)
    {
    case 1:
        kont->key = LangProg::key::PROCEDURN;
        readPr(kont->spec, ifst);
        return kont;
    case 2:
        kont->key = LangProg::key::OBOR;
        readObOr(*static_cast<ObOr*>(kont->spec), ifst);
        return kont;
    default:    // нет совпадений -> нет записи
        exit;
    }
}

как быть?

Добавлено через 1 час 46 минут
хм...
любопытно
ну можно такой вариант
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
void readPr(void** Procedurn, ifstream &ifst)
{
    bool gl;
    ifst >> gl;
    *Procedurn = (bool *)&gl;
}
 
LangProg* InLangP(ifstream &ifst)   
{
    
    LangProg *kont = new LangProg;
    int prov;
    ifst >> prov;
    switch (prov)
    {
    case 1:
        kont->key = LangProg::key::PROCEDURN;
        readPr(&kont->spec, ifst);
        return kont;
    case 2:
        kont->key = LangProg::key::OBOR;
        readObOr(&(kont->spec), ifst);
        return kont;
    default:    // нет совпадений -> нет записи
        exit;
    }
}
Добавлено через 17 секунд
ну или все же с void* работает "у страха глаза велики... Да, у enum нельзя считывать сразу:

C++
1
2
3
4
5
6
7
(enum ObOr{UNO = 1, MANY, INTARFACE };
//...
ObOr a;
//cin >> a; // ошибка, необходимо:
int tmp;
cin >> tmp;
a = static_cast<ObOr >(tmp);
да и у void* нельзя просто приравнять:
C++
1
2
3
4
void* a;
int b = 5;
//a = b // ошибка, надо:
a = (int*)b;
ну и два этих фактора вызвали вариант сверху

Добавлено через 3 минуты
а в итоге то все намного просто

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
void readPr(void** Procedurn, ifstream &ifst)
{
    ifst >> *Procedurn;
}
 
LangProg* InLangP(ifstream &ifst)   
{
 
    LangProg *kont = new LangProg;
    int prov;
    ifst >> prov;
    switch (prov)
    {
    case 1:
        kont->key = LangProg::key::PROCEDURN;
        readPr(&kont->spec, ifst);
        break;
    case 2:
        kont->key = LangProg::key::OBOR;
        readObOr(&kont->spec, ifst);
        break;
    default:  
        exit;
    }
    return kont;
    
}
просто и элементарно ifst >> *Procedurn

ну главное разобралась
типо
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
20.11.2018, 22:30
Ответы с готовыми решениями:

Указатель типа void
Добрый день. enum Type { Double, Int, Float }; void func(int k,enum Type t,...) { void...

Указатель типа void c++
Haпример указатель типа void*ptr char *p void *ptr=&quot;abs&quot;; p=((char *)ptr);Так указатель...

Функция принимает указатель на void и возвращает указатель на int
Запишите прототип функции, которая принимает указатель на void и возвращает указатель на int.

Обобщенный указатель типа void
В приложенной картинке рассказывается о динамическом распределении памяти в С. Сказано, что функция...

3
18472 / 9629 / 2356
Регистрация: 30.01.2014
Сообщений: 16,882
20.11.2018, 22:56 2
Лучший ответ Сообщение было отмечено tupen_T_T как решение

Решение

tupen_T_T, гаданием занимаетесь, вы знаете?

В первом вашем варианте за указателем ничего не стоит. Память не выделена, указатель не инициализирован. Любая попытка чтения из него приводит к UB.

Вот вам примерчик на коленке.
Кликните здесь для просмотра всего текста
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
struct LangProg  // как раз обобщение
{
    enum key_ 
    { 
        BOOL = 1, INT 
    };
    
    ~LangProg()
    {
        switch(key)
        {
        case BOOL:
            delete static_cast<bool *>(spec);
            break;
        case INT:
            delete static_cast<int *>(spec);
            break;            
        }
    }
    
    LangProg() : key(), spec()
    { }
    LangProg(int v)  : key(INT), spec(new int(v))
    { }
    LangProg(bool v) : key(BOOL), spec(new bool(v))
    { } 
    
    LangProg(LangProg const & x)
        : key(x.key), spec(copy(x))
    { }
    
    static void * copy(LangProg const & x)
    {
        switch(x.key)
        {
        case BOOL:
            return new bool(*static_cast<bool*>(x.spec));
        case INT:
            return new int(*static_cast<int*>(x.spec));
        }
        return 0;
    }
    
    void swap(LangProg & other)
    {
        std::swap(spec, other.spec);
        std::swap(key, other.key);
    }
    
    LangProg & operator=(int v)
    {
        LangProg(v).swap(*this);
        return *this;
    }
    LangProg & operator=(bool v)
    {
        LangProg(v).swap(*this);
        return *this;
    }
    
    friend std::ostream & operator<<(std::ostream & out, LangProg const & x)
    {
        if(x.spec && x.key != LangProg::key_())
        {
            switch(x.key)
            {
            case BOOL:
                out << *static_cast<bool*>(x.spec);
                break;
            case INT:
                out << *static_cast<int*>(x.spec);
                break;
            }
        }
        return out;
    }
    
private:
    key_ key; // по ключу определяем тип
    void * spec;    
};
 
void readBool(bool & v, std::istream &ifst)
{
    ifst >> v;
}
 
void readInt(int & v, std::istream &ifst)
{
    ifst >> v;
}
 
LangProg InLangP(std::istream & ifst) 
{
    LangProg kont;
    int prov;
    ifst >> prov;
    switch(prov)
    {
    case LangProg::INT:
        {
            int v;
            readInt(v, ifst);
            kont = v;
        }
        break;
    case LangProg::BOOL:
        {
            bool v;
            readBool(v, ifst);
            kont = v;
        }
        break;
    }
    return kont;
}


Добавлено через 56 секунд
Цитата Сообщение от tupen_T_T Посмотреть сообщение
а в итоге то все намного просто
Уверены?

Цитата Сообщение от tupen_T_T Посмотреть сообщение
ну главное разобралась
Рано расслабляться.
1
0 / 0 / 0
Регистрация: 12.04.2016
Сообщений: 75
03.12.2018, 21:43  [ТС] 3
спасибо!!!


это решение теперь точно работает, но с точки реализации не посмотрите? Ну тупо реализовано с void* или норм?



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
enum ObOr { UNO = 1, MANY, INTARFACE };
struct LangProg
{
    enum key { PROCEDURN = 1, OBOR } key;
    void* spec;
    unsigned short int god;
};
 
void INO(void* &a, ifstream &ifst)
{
    a = new ObOr;
    int bv;
ifst >> bv;
    ObOr ui;
    ui = static_cast<ObOr>(bv);
    swap(*(ObOr*)a, ui);
}
 
void INP(void* &a, ifstream &ifst)
{
    a = new bool;
    bool bv;
    ifst >> bv;
    swap(*(bool*)a, bv);
}
 
LangProg* InLangP(ifstream &ifst)
{
    LangProg *kont = new LangProg;
    int prov;
    if (ifst >> prov)
    {
        switch (prov)
        {
        case 1:
            kont->key = LangProg::key::PROCEDURN;
            INP(kont->spec, ifst);
            break;
        case 2:
            kont->key = LangProg::key::OBOR;
            INO(kont->spec, ifst);
            break;
        default:   
            exit(0);
        }
        if (ifst >> kont->god)
        {
            return kont;
        }   
    }
}
0
18472 / 9629 / 2356
Регистрация: 30.01.2014
Сообщений: 16,882
03.12.2018, 22:24 4
tupen_T_T, есть лишние действия. Например вы могли бы сразу читать в выделенный объект, а не создавать промежуточный.
C++
1
2
3
4
5
6
7
8
void INO(void* &a, ifstream &ifst)
{
    ObOr * pOb = new ObOr;
    int bv;
    ifst >> bv;
    *pOb = bv;
    a = p;
}
C++
1
2
3
4
5
6
void INP(void* &a, ifstream &ifst)
{
    bool * p = new bool;
    ifst >> *p;
    a = p;
}
Также нигде не видно, чтобы вы освобождали выделенные ресурсы (в моем коде это сделано).
Также функция InLangP возвращает значение не на всех путях выполнения - это некорректно.
0
03.12.2018, 22:24
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
03.12.2018, 22:24
Помогаю со студенческими работами здесь

Указатель типа void: зачем они нужны?
Здравствуйте! Начал изучать Язык С, в книжке написано: Только не понятно зачем нужны такие...

Указатель типа void на функцию, вызов функции
Необходимо с помощью указателя типа void запустить функцию. void func(int); int main(){ void...

Специализация и обобщение в С++ через универсальный указатель
Здравствуйте, уважаемые участники форума! Возникла следующая проблема. Необходимо написать...

Указатель типа void - пояснить несколько строк кода
Ну вот вроде разобрался с указателями и начал разбираться с указателями типа void и сразу же...

Универсальный вызов метода через указатель на объект
Никак не могу найти универсальную конструкцию, которая позволяла бы вызывать любой метод класс, с...

Как узнать тип, переданный через указатель на void?
есть функция, принимает LPVOID, нужно узнать как тип переменной был передан, и сколько занимает в...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru