C ++ Понижение структуры - PullRequest
0 голосов
/ 07 июня 2018

У меня есть следующий код:

struct Operation {
    public :
        OperationName name;
};

struct FilterOperation : Operation {
    FilterName filter;
    std::list<std::string> params;
};

OperationName и FilterName представляют собой перечисления, перечисляющие все различные имена каждой операции и фильтра.

В a для каждого цикла, проходящего через всеОперации, я хочу понизить Операцию до FilterOperation:

std::list<Operation> operations
for (Operation op : operations) {
switch (op.name) {
    case o_filter :
        std::cout  << dynamic_cast<FilterOperation*>(&op)->filter << std::endl;
    }
}

Очевидно, что dynamic_cast здесь не работает:

parser.cpp:154:90: error: cannot dynamic_cast ‘& op’ (of type ‘struct Operation*’) to type ‘struct FilterOperation*’ (source type is not polymorphic)
 "Op: Filter, Name: " << filterStrings[dynamic_cast<FilterOperation*>(&op)->filter] 

Я фактически пытался добавить к нему виртуальную функцию, ноэто не решает мою реальную проблему (я не могу понять, как правильно опускать здесь)

Ответы [ 3 ]

0 голосов
/ 07 июня 2018

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

В любом случае, поскольку вы имеете дело с экземплярами объектов, а не указателями, это никогда не сработает.Ваш список состоит из объектов Operation, not объектов FilterOperation.Если вы хотите вставить объекты FilterOperation, вам нужен список указателей (или, предпочтительно, shared_ptr) вместо хранения по значению:

std::list<Operation*> operations
for (Operation* op : operations) {
switch (op->name) {
    case o_filter :
        std::cout  << dynamic_cast<FilterOperation*>(op)->filter << std::endl;
    }
}

Кроме того, я подозреваю, что вы неправильно понимаете, что switch () будет делать для символьных строк,Вероятно, он не будет делать то, что вы хотите, и вместо этого вам понадобится оператор if.

0 голосов
/ 07 июня 2018

Используя контейнеры stl, вы используете конструктор копирования и operator = из Operation.Эти методы копируют только Operation из FilterOperation, а не всю структуру.

Чтобы решить проблему, вы должны использовать std::list<Operation*> или даже лучше, std::list<std::shared_ptr<Operation>> вместо std::list<Operation>

, чтобы вы не копировали Операцию в список, а толькоуказатель ...

Кроме того , вы должны добавить виртуальный деструктор в структуру Operation, иначе у вас будет утечка памяти из-за списка в производном классе (FilterOperation) не будет освобожден при удалении Operation.

0 голосов
/ 07 июня 2018

Это неопределенное поведение.

op - это Operation.Не указатель или ссылка на Operation, меньше на FilterOperation.Так что &op явно не является FilterOperation*.

С сайта cppreference.com по dynamic_cast :

dynamic_cast < new_type > ( expression )      

Если приведение выполнено успешно, dynamic_castвозвращает значение типа new_type.Если приведение завершается неудачно и new_type является типом указателя, он возвращает нулевой указатель этого типа.

Очевидно, что dynamic_cast<FilterOperation*>(&op) - это нулевой указатель, а разыменование это UB.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...