当放置在容器中时,C++子类型退化
C++ subtype degeneration when placed in a container
我目前正在学习一门来自java背景的c++课程。
我们现在已经到了讨论继承的地步。这周的课并没有真正解释每周作业需要做什么,这让我在试图解决这些问题时有些不知所措。
虽然我会抽出时间问我的导师,但这意味着要等到下周,让我落后。
请允许我展示我想做的事情:
class base
{
int field1;
base(int _field):
field1(_field){}
};
class subclass : public base
{
int field2;
public:
subclass(int _field2):
base(_field1),field2(_field2){}
string to_string()
{
return "I am a subtype!!";
}
};
int main()
{
vector<base> x;
x.push_back(subclass(123,456));
cout<<x[0].to_string[]<<end; //error!!
}
令我惊讶的是,这段代码无法工作,甚至无法编译。容器x将把其中的对象强制转换为基类型,这意味着我被迫将曾经的子类型视为基类型。这意味着子类型变量和函数遥不可及。
我想做的是将容器中的对象视为子类型,IE对它们进行类型测试(这本身就是一件小事),然后根据对象的类型做不同的事情。
这在java中是微不足道的。在那里,我可以简单地用子类型填充一个类型库数组,然后对其中的对象执行我想要的任何操作。
我假设我在java中所做的,在C++中应该是可能的,能够将子类型放入某种容器中,然后将它们视为应该可能的子类型。很明显,我在这里误解了一些基本的东西,这个问题对我来说是完全不可预见的
值得一提的是,我在向量和简单数组中都尝试过这种方法。出现了完全相同的模式,数组的类型决定了我如何访问对象,即我不能调用to_string()。
总结一下:我想知道如何在容器中包含子类型,而不让容器将内部的对象强制转换为容器的类型。
这在Java中是微不足道的。在那里,我可以简单地用子类型填充一个类型库数组,然后对其中的对象执行我想要的任何操作。
Java和C++中对象的主要区别在于,所有Java对象都是通过引用访问的(有点类似于C++智能指针),而在C++中,您可以选择直接访问对象。这可以很好地工作,并使用非多态对象节省大量内存和一些CPU周期,但由于对象切片,一旦继承进入阶段,就会显著中断。
把十磅的东西放进一个五磅的袋子是个问题:vector<base>
分配了足够的空间来容纳base
类型的N
项目,所以当你试图把subclass
放进同一个空间时,编译器告诉你它不适合。
要解决这个问题,请模仿Java的做法,即使用智能指针:
vector<unique_ptr<base> > x;
unique_ptr<base> item(new subclass(123,456));
x.push_back(std::move(item));
演示。
注意:您的代码中有几个问题需要修复才能正常工作。首先,向base
添加一个公共to_string
成员函数。然后,将通过点.
运算符对to_string
的调用替换为通过箭头->
运算符的调用。最后,修复一些拼写错误——to_string
调用中的方括号,以及endl
中缺少的l
。
- ArduinoJson 6.15.2:JsonObject没有命名类型
- 防止主数据类型C++的隐式转换
- 大量序列中核苷酸类型的快速计数
- 如何从C++中的依赖类型中获得它所依赖的类型
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如何获取std::result_of函数的返回类型
- 从父命名空间重载类型
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 访问者访问变体并返回不同类型时出错
- 在VS2010-VS2015下编译时,如何使用decltype作为较大类型表达式的LHS
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 模板元程序查找相似的连续类型名称
- 是否可以从int转换为enum类类型
- 构造函数正在调用一个使用当前类类型的函数
- 我应该使用什么来代替void作为变体中的替代类型之一
- 类中的字符串不命名类型