7 / 6 / 1
Регистрация: 29.10.2016
Сообщений: 175
1

Некорректный указатель на абстрактный класс

28.05.2020, 14:36. Показов 378. Ответов 6
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Доброго времени суток.
Для удобства создал пример.
Понимаю, что ошибка в функции getChild(). C указателем Parent* эта функция отрабатывает правильно и возвращает указатель на SndChild.
Но!
Я теряю возможность использовать функцию setField(). А это необходимо. Как можно исправить это?
Есть важное условие: Разрешено полностью изменять функцию getChild() и определение функции update() в классе SndChild, все остальное изменять крайне не желательно.
Так вот, какие будут у Вас мысли?

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
#include <iostream>
#include <memory>
#include <map>
 
class Parent {
public:
    virtual void update(Container& container) = 0;
 
    virtual ~Parent() = default;
};
 
//Хранит в себе элемент и выводит его значение
class FstChild : public Parent {
private:
    int filed_{ 0 };
public:
    FstChild() {};
 
    void setField(int val) {
        filed_ = val;
    }
 
    void update(Container& container) override {
 
        std::cout << "My value: "<< filed_<< "\n";
    }
 
    ~FstChild() override = default;
};
 
// Устанавливает значение другого класса
class SndChild : public Parent {
public:
    SndChild() {};
 
    void update(Container& container) override {
 
        FstChild* fst = container.getChild<FstChild>(2);
 
        fst->setField(20);
 
        std::cout << "FstChild updated\n";
    }
    
 
    ~SndChild() override = default;
};
 
// Контейнер, хранит в себе две системы
class Container {
private:
    std::map<int, std::unique_ptr<Parent>> storage_;
    //[1, SndChild] - обработчик
    //[2, FstChild] - вывод
public:
    Container() {
        //1st 
        std::unique_ptr<FstChild> buffFst(new FstChild());
        storage_.insert(std::make_pair(2, std::move(buffFst)));
        //2nd
        std::unique_ptr<SndChild> buffSnd(new SndChild());
        storage_.insert(std::make_pair(1, std::move(buffSnd)));
    };
    
    template <typename TChild>
    TChild* getChild(size_t childID) {
        auto pointer = storage_.at(childID).get();
        return pointer;
    }
 
    void containerUpdate() {
        for (auto& it : storage_) {
            storage_.at(it.first)->update(*this);
        }
    }
 
    ~Container() = default;
};
 
 
 
 
int main() {
    std::shared_ptr<Container> cont (new Container());
    cont->containerUpdate();
 
    /*
    Вывод в консоль должен выглядеть так:
 
    FstChild updated
    My value: 20
    
    */
 
    system("pause");
    return 0;
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
28.05.2020, 14:36
Ответы с готовыми решениями:

Указатель на абстрактный шаблонный класс
Есть абстрактный шаблон класса и 3 производных от него шаблонов классов. Так же есть шаблонная...

Указатель на бызовый абстрактный класс.
Правильно ли у меня написан &quot;умный&quot; указатель? Напонятно, как можно с помощью указателя на базовый...

Что такое указатель на абстрактный класс?
В задании сказано - Методы класса должны принимать указатель на абстрактный класс , что это значит...

Скопировать объект, на который ссылается указатель на абстрактный класс
Доброго времени суток. У меня такое задание: написать программу символьного дифференцирования, т.е....

6
El. Psy. Congroo.
110 / 92 / 32
Регистрация: 09.01.2018
Сообщений: 344
28.05.2020, 15:26 2
Добавить чистый виртуальный метод setField в базовый класс.
0
7 / 6 / 1
Регистрация: 29.10.2016
Сообщений: 175
28.05.2020, 15:34  [ТС] 3
Цитата Сообщение от Mightsoul Посмотреть сообщение
Добавить чистый виртуальный метод setField в базовый класс.
Это запрещено.

Добавлено через 6 минут
Там еще в самом начале добавьте строчку:
C++
1
class Container;
пропустил я её.
0
6091 / 3449 / 1402
Регистрация: 07.02.2019
Сообщений: 8,769
28.05.2020, 15:54 4
Цитата Сообщение от Battary Посмотреть сообщение
C++
1
2
3
    void update(Container& container) override {
 
        FstChild* fst = container.getChild<FstChild>(2);
Определение этого метода должно находиться после определения класса Container

Добавлено через 1 минуту
Цитата Сообщение от Battary Посмотреть сообщение
C++
1
TChild* getChild(size_t childID)
Может лучше дать контейнеру решать, по какому ID у него лежит указатель на нужного вам потомка?
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
28.05.2020, 16:01 5
Цитата Сообщение от Battary Посмотреть сообщение
FstChild* fst = container.getChild<FstChild>(2);
ты же уже указал тип объекта, который тебе нужен.
зачем нужен ещё какой то дополнительный айдишник?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
    template <typename TChild>
    TChild& getChild() 
    {
        const size_t id = typeid(TChild).hash_code();
 
        #ifdef NDEBUG // release
            TChild* pointer = static_cast<TChild*>(storage_.at(id).get());   
        #else 
            TChild* pointer = dynamic_cast<TChild*>(storage_.at(id).get());            
        #endif 
        assert(pointer);
        return *pointer;
    }
идентификатор типа извлекается из самого типа.

не очень понятно: нафига ты решил использовать юник_птр?
1
7 / 6 / 1
Регистрация: 29.10.2016
Сообщений: 175
28.05.2020, 16:03  [ТС] 6
Цитата Сообщение от zayats80888 Посмотреть сообщение
Определение этого метода должно находиться после определения класса Container

Может лучше дать контейнеру решать, по какому ID у него лежит указатель на нужного вам потомка?
1. Можно, а можно объявить в самом начале.
2. В настоящем проекте контейнер сам решает, просто хотелось максимально упростить пример, чтобы не пришлось долго его изучать. Экономлю ваше время.
0
6091 / 3449 / 1402
Регистрация: 07.02.2019
Сообщений: 8,769
28.05.2020, 16:11 7
Цитата Сообщение от Battary Посмотреть сообщение
1. Можно, а можно объявить в самом начале.
Я про определение. Вы вызываете метод класса, который не объявлен. Вы не можете использовать неполный тип, кроме как в качестве ссылок/указателей и в объявлениях.

Добавлено через 4 минуты
Battary, пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct SomeClass;// неполный тип
 
struct AnotherClass
{
    void foo(SomeClass& s);//объявление
};
 
struct SomeClass
{
    void bar();
};
 
void AnotherClass::foo(SomeClass& s)//определение
{
    s.bar();//теперь видим метод SomeClass::bar()
}
1
28.05.2020, 16:11
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
28.05.2020, 16:11
Помогаю со студенческими работами здесь

Создание объекта через указатель на базовый абстрактный класс
Есть абстрактный класс, от него наследуется 3 класса. В программе предусмотрено создание нового...

Создать абстрактный тип данных - класс вектор, который имеет указатель на long, число элементов и переменную состояния
Помогите пожалуйста, нужно написать код на с++ Создать абстрактный тип данных - класс вектор,...

Класс: Разработать абстрактный класс класс Point для задания координаты...
Всем привет, помогите пожалуйста решить задачу, я уже всю голову сломал, не знаю как решить... ...

Буст сериализация. указатель на абстрактный базовый класс без конструктора по умолчанию
Читая документацию по сериализации с помощью буста запутался. Ситуация следующая. Имеется...

Как создать указатель на абстрактный класс для дальнейшего помещения в список?
Как создать указатель на абстрактный класс в Windows Form для дальнейшего помещения в список итд? ...

Класс: Формальным параметром метода должна быть ссылка на абстрактный класс...
&quot;Формальным параметром метода должна быть ссылка на абстрактный класс или наиболее общий интерфейс...


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

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

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