Невозможно использовать методы подкласса Y после помещения его в std :: stack <ParentClass>(C ++) - PullRequest
0 голосов
/ 15 апреля 2019

Я пытаюсь создать свой собственный язык программирования. Виртуальная машина для этого языка будет использовать стек данных , в который будут выталкиваться и извлекаться все объекты.

Теперь, очевидно, std::stack позволяет вставлять в него только элементы того же типа , поэтому я создал очень общий класс Obj, который станет родительским классом для всех других типов данных, таких как Num, Chr и т. д. *

class Obj
{
    std::string type;

    public:
    void set_type(std::string type) { this->type = type; }
    std::string get_type() { return this->type; }
};

Чтобы привести пример подкласса Num:

class Num : public Obj
{
    double value;

    public:
    Num (double value)
    {
        this->set_type("num");
        this->value = value;
    }

    double get_value() { return this->value; }
};

Проблема стала очевидной позже ... Я писал функцию EMIT_CONST, которая должна извлекать элемент из верхней части стека и выводить его на стандартный вывод. Чтобы дать вам больше информации о том, как все выглядит:

std::stack<Obj> data;

void emit_const(std::stack<Obj> &data)
{
    if ( data.empty() ) return; // some error checking

    std::string type = data.top().get_type();

    if (type == "bln")
    {
        Bln bln = data.top(); data.pop();
        std::cout << bln.get_value() ? "true" : "false";
    }

    else if (type == "chr")
    {
        Chr chr = data.top(); data.pop();
        std::cout << chr.get_value();
    }

    // ... and so on for the rest of the types
}

Когда я пытался скомпилировать это, компилятор GNU g ++ выдал мне ошибку:

conversion from ‘__gnu_cxx::__alloc_traits<std::allocator<Obj> >::value_type {aka Obj}’ 
to non-scalar type ‘Bln’ requested
         Bln bln = data.top(); data.pop();

Это то же сообщение об ошибке было дано для каждой строки кода, где я в основном пытаюсь интерпретировать Obj как его подкласс, такой как Bln или Num, чтобы иметь возможность использовать их методы, которые не определены в общий Obj класс.

Как я понимаю, после помещения любого экземпляра подкласса Obj, например Bln, в std::stack<Obj>, этот экземпляр удаляется из его методов и членов, которые не объявлены в родительском классе Obj ( Я сделал это, основываясь на том факте, что строка std::string type = data.top().get_type(); не генерирует ошибку). Такое поведение разумно с точки зрения C ++. Тем не менее, мне все еще нужно заставить эту вещь работать, и я должен иметь возможность использовать методы этих элементов, когда они выпадают. Пожалуйста, помогите мне решить это эффективным способом! Заранее спасибо.

Если вы хотите взглянуть на общее расположение кода: GitHub Repo

1 Ответ

1 голос
/ 15 апреля 2019

Здесь есть две проблемы: get_type должен быть виртуальным, и когда вы используете std::stack<Obj>, он удаляет все данные.

Когда вы используете std::stack<Obj>, он сначала приводит его к объекту.и удаляет все свойства num.Когда вы пытаетесь привести его обратно к исходному типу, он не может этого сделать, потому что он хранит только свойства Obj, а не информацию о подклассах.Чтобы это исправить, вы должны либо сохранить ссылку на нее (std::stack<Obj&>), либо сделать копию и сохранить ее в куче (std::stack<std::unique_ptr<Obj>>), чтобы она могла хранить информацию из подклассов.

Во-вторых, вам нужно объявить get_type как виртуальный.Виртуальное - это ключевое слово, которое указывает классу хранить информацию о том, какой это тип.Это позволяет программе вызывать правильный метод.Если вы не используете это, вместо этого всегда будет вызываться версия родительских классов (Obj).

...