将子类Y推入std :: stack <parentclass>(C ++)后无法使用它的方法

时间:2019-04-15 02:09:24

标签: c++ class c++11 stack subclass

我正在尝试创建自己的编程语言。该语言的虚拟机将使用数据堆栈,其中所有对象都将被推入和弹出。

现在,很显然,std::stack仅允许将相同类型的元素放入其中,因此,我创建了一个非常通用的Obj类,该类将所有其他数据类型(例如NumChr等)的父类……

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解释为其子类,例如BlnNum的每一行代码都给出了相同的错误消息,以便能够使用它们常规Obj类中未定义的方法。

据我了解,将Obj的子类的任何实例(如Bln推入std::stack<Obj>之后,该实例将被剥离其未在方法中声明的方法和成员。父Obj类(我根据行std::string type = data.top().get_type();不会产生错误这一事实进行推断)。从C ++的角度来看,这种行为是合理的。尽管如此,我仍然需要使该东西正常工作,并且当它们弹出时,我需要能够使用这些方法。请帮助我以有效的方式解决该问题!预先感谢。

如果您希望查看常规代码布局:GitHub Repo

1 个答案:

答案 0 :(得分:1)

这里有两个问题:get_type必须是虚拟的,而当您使用std::stack<Obj>时,它将删除所有数据。

使用std::stack<Obj>时,它首先将其强制转换为Obj并删除num的所有属性。当您尝试将其强制转换回其原始类型时,不能这样做,因为它仅存储了Obj的属性,而不存储了子类信息。为了解决此问题,您必须保留对其的引用(std::stack<Obj&>)或对其进行复制并将其存储在堆中(std::stack<std::unique_ptr<Obj>>),以便它可以保留子类中的信息

第二,您需要将get_type声明为虚拟的。 Virtual是一个关键字,它告诉类存储有关其类型的信息。这使程序可以调用正确的方法。如果不使用此选项,将始终调用父类版本(Obj)。