40 / 29 / 11
Регистрация: 21.06.2019
Сообщений: 201
1

как генерировать ошибку компиляции при вызове виртуального метода

06.07.2021, 14:56. Показов 1663. Ответов 2
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Задач стоит следующая, по сути реализуется паттерн машина состояний, что-то такое:
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
#include <iostream>
#include <memory>
#include <stack>
 
struct Json {
private:
    using handler_t = std::unique_ptr<struct CommandHandler>;
    std::stack<handler_t> cmd_handlers;
    handler_t &get_current(){
        return cmd_handlers.top();
    }
    void pop_current() {
        cmd_handlers.pop();
    }
    std::ostream & out;
public:
    explicit Json(std::ostream & o) : out(o) {}
 
    void output(std::string_view str){
        out << str;
    }
 
    void set_current(std::unique_ptr<struct CommandHandler> new_handler){
        if (cmd_handlers.empty())
            throw std::logic_error("JSON allows only one top-level value");
        cmd_handlers.push(std::move(new_handler));
    }
 
    Json &Number(int64_t);
    Json &String(std::string_view);
    Json &Boolean(bool);
    Json &Null();
    Json &Key(std::string_view);
    Json &BeginArray();
    Json &EndArray();
    Json &BeginObject();
    Json &EndObject();
};
 
#define ERROR_MESSAGE {throw std::logic_error("Invalid continuation"); }
 
struct CommandHandler {
public:
    virtual void Number(Json *, int64_t) ERROR_MESSAGE;
    virtual void String(Json *, std::string_view) ERROR_MESSAGE;
    virtual void Boolean(Json *, bool) ERROR_MESSAGE;
    virtual void Null(Json *) ERROR_MESSAGE;
    virtual void Key(Json *, std::string_view) ERROR_MESSAGE;
    virtual void BeginArray(Json *) ERROR_MESSAGE;
    virtual void EndArray(Json *) ERROR_MESSAGE;
    virtual void BeginObject(Json *) ERROR_MESSAGE;
    virtual void EndObject(Json *) ERROR_MESSAGE;
};
 
Json &Json::Number(int64_t num) {
    get_current()->Number(this, num);
    return *this;
}
 
Json &Json::String(std::string_view str) {
    get_current()->String(this, str);
    return *this;
}
 
Json &Json::Boolean(bool b) {
    get_current()->Boolean(this, b);
    return *this;
}
 
Json &Json::Null() {
    get_current()->Null(this);
    return *this;
}
 
Json &Json::Key(std::string_view str) {
    get_current()->Key(this, str);
    return *this;
}
 
Json &Json::EndArray() {
    get_current()->EndArray(this);
    pop_current();
    return *this;
}
 
Json &Json::EndObject() {
    get_current()->EndObject(this);
    pop_current();
    return *this;
}
 
struct StringHandler : public CommandHandler {
//...
};
 
struct ArrayHandler : public CommandHandler {
//...
};
 
Json &Json::BeginArray() {
    set_current(std::make_unique<ArrayHandler>());
    get_current()->BeginArray(this);
    return *this;
}
 
struct ObjectHandler : public CommandHandler {
//...
};
 
Json &Json::BeginObject() {
    set_current(std::make_unique<ObjectHandler>());
    get_current()->BeginObject(this);
    return *this;
}
 
struct KeyHandler : public CommandHandler {
//...
};
Смысл этого кода при определенном хендлере поддерживать только определенные методы над основной структурой (ее тут зовут Json), сами хендлеры хранятся у нее в стеке. И как можно заметить абстрактный класс CommandHandler, кт реализует интерфейс для всех хэндлеров у себя генерирует исключение (макрос ERROR_MESSAGE). Но мне необходимо генерировать не исключение, а ошибку компиляции. То есть если текущий хэндлер - это StringHandler, то у него не может быть вызван метод EndArray, и место такого вызова не должно компилироваться.

Отсюда вопрос:
Как можно реализовать такую конструкцию (можно ли вообще), чтобы метод был в интерфейсе абстрактного класса, но его вызов в наследнике выдавал ошибку компиляции? Возможно стоит засунуть такие методы в private, но мб есть способ очевиднее и лучше. Заранее благодарю!
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
06.07.2021, 14:56
Ответы с готовыми решениями:

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

При вызове метода функционального объекта в шаблонной функции ошибка компиляции C2039
Объект класса Entry - это запись в журнале экзаменационной сессии: номер зачетки, фамилия, курс,...

Выбивает ошибку при вызове метода
При вызове метода в 35 строке выскакивает ошибка: ссылка на обьект не указывает на экземпляр...

Исправить ошибку при вызове метода AddPicture коллекции Shapes
надо создать программу в word которая бы создавала презентацию со слайдами на которых картинки Я...

2
124 / 44 / 15
Регистрация: 01.11.2020
Сообщений: 122
06.07.2021, 15:48 2
Лучший ответ Сообщение было отмечено HamsterGamer как решение

Решение

не понял зачем нужен вызов в наследнике.
сделайте композицию вместо наследования. чтобы у наследника вообще не было этого метода.
...
лан . это увидел...


или так тогда

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
#include <iostream>
 
class AbstractBase
{
public:
    void method();
};
 
class Derived: public AbstractBase
{
public:
    void method()= delete;
};
 
class Derived2: public AbstractBase
{
public:
    void method(){ std::cout << "Derived2::method\n";}
};
 
int main()
{
    Derived der;
   // der.method(); // error: use of deleted function ‘void Derived::method()
    Derived2 der2;
    der2.method();
}
Добавлено через 17 минут
тут сама ошибка в проектировании .
базовый класс должен давать основу дочерним .
дочерние уже расширяют функционал. это в идеале.

нужен не абстрактный класс, а интерфейс.
1
40 / 29 / 11
Регистрация: 21.06.2019
Сообщений: 201
06.07.2021, 16:40  [ТС] 3
stepForward,
Цитата Сообщение от stepForward Посмотреть сообщение
тут сама ошибка в проектировании
не сказал бы что ошибка в проектировании. Я должен либо определить методы, либо сделать их невалидными. Но они должны быть в каждом наследнике, потому что я вызываю их от указателя на базовый класс.

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

Добавлено через 5 минут
Вообщем я чета бред пронес, виртуальный полиморфизм только во время выполнения работает. А следовательно ошибок компиляции все равно не будет, но кажется я придумал вариант (использовать variant на наследники вместо указателей на базовый класс!).
0
06.07.2021, 16:40
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
06.07.2021, 16:40
Помогаю со студенческими работами здесь

При компиляции выдает ошибку "C2078: слишком много инициализаторов" при вызове MessageBox
Здравствуйте! Уже целый день бьюсь над заданием. Осталась самая малость. Помогите, пожалуйста! ...

Как указывать аргументы при вызове одного метода из другого?
Добрый день! Прошу прощения за совсем примитивизм: public void panel1_paint(Object sender,...

Как узнать сколько было блокировок при вызове метода
привет есть многопоточное приложение использую synclock можно как то узнать как часто потоки...

JS: Как заменить свойство объекта при вызове его метода?
const Some = { hello: 'hello', sayHello: function() { console.log( this.hello ); }, ...

Как добиться неизменности параметра метода при его вызове?
Хочу чтобы параметр метода не менялся внутри него. Пишу так void someFunction(final SomeObject...

Вызов виртуального метода при создании
Добрый вечер, библиотека навязала следующее поведение: - объект создан и валиден, если...


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

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

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