简体   繁体   English

C ++继承在子类的变量上调用child的函数

[英]C++ inheritance calling functions from child on a variable of the parent class

In C++ I have a base class Packet and then a lot of children APIPacket, DataIOPacket etc. Now I want to store an incoming packet and since I don't know the type I store this in a variable: 在C ++中,我有一个基类包,然后有很多孩子APIPacket,DataIOPacket等。现在我想存储一个传入的数据包,因为我不知道我在变量中存储它的类型:

Packet packet;
packet = DataIOPacket();

But now DataIOPacket has a function getAnalogData(); 但是现在DataIOPacket有一个函数getAnalogData(); I can't do: 我做不到:

packet.getAnalogData();

Since packet doesn't have this function. 由于数据包没有此功能。 In java I think this is possible since the actual type of the object stored in packet is not lost (is this correct?). 在java中我认为这是可能的,因为存储在数据包中的对象的实际类型不会丢失(这是正确的吗?)。 But in C++ my DataIOPacket is narrowed into a Packed and loses it's functions that haven't been declared in Packet. 但是在C ++中,我的DataIOPacket缩小为Packed并丢失了尚未在Packet中声明的函数。

You could make a virtual function in Packet for every function in every child. 您可以在Packet中为每个孩子的每个功能创建一个虚拟功能。 But for me this would mean a lot of functions in Packet which in most cases should not be called. 但对我来说,这意味着Packet中的许多功能在大多数情况下都不应该被调用。 It has no use calling getAnalogData() on an APIPacket. 在APIPacket上调用getAnalogData()是没有用的。

How is this problem solved? 这个问题怎么解决了? I can't find the answer but I feel a lot of people must encounter it. 我找不到答案,但我觉得很多人都必须遇到它。

You could do something with typecasting back to DataIOPacket and APIPacket but this doesn't really seem a clean solution either. 您可以通过类型转换回DataIOPacket和APIPacket来做一些事情,但这似乎也不是一个干净的解决方案。

Are there maybe libraries that solve my problem? 是否有可能解决我问题的库?

Rgds, RGDS,

Roel 罗埃尔

This is possible in java and in c++ too. 这在java和c ++中也是可能的。 you need to do a dynamic_cast to check for the type. 你需要做一个dynamic_cast来检查类型。

 Packet* packet;
packet = new DataIOPacket();

      DataIOPacket dio* = dynamic_cast<DataIOPacket*>(packet); 
            if (dio != 0)
            {
             dio->DoSomeChildMethodStuff();
            }

in C++ my DataIOPacket is narrowed into a Packet and loses it's functions that haven't been declared in Packet 在C ++中,我的DataIOPacket被缩小为一个Packet并丢失了尚未在Packet声明的功能

It happens because you assign the object of type DataIOPacket to the object of type Packet , which results in this object being sliced (see What is object slicing? ). 之所以发生这种情况,是因为您将DataIOPacket类型的对象分配给Packet类型的对象,这会导致此对象被切片 (请参阅什么是对象切片? )。

What you are actually looking for is a way how you could find out in run-time , whether the object that you are working with has been created as an instance of DataIOPacket . 您实际需要的是一种如何在运行时找到您正在使用的对象是否已创建为DataIOPacket实例的DataIOPacket In other words you are looking for Run-Time Type Identification (RTTI) . 换句话说,您正在寻找运行时类型识别(RTTI)

To avoid slicing , you need to have a reference or a pointer to the object. 要避免切片 ,您需要有一个引用或指向该对象的指针。 Type of this object will be then identified in run-time : 然后将在运行时标识此对象的类型:

Packet* packet;
packet = new DataIOPacket();

now packet is a pointer to the object of type DataIOPacket ( run-time ), but the type of the pointer is Packet* ( compile time ). now packet是指向DataIOPacket类型( 运行时 )的对象的指针,但指针的类型是Packet*编译时 )。 In order to invoke a method that is specific for DataIOPacket class on this object, the compiler needs to know that this pointer points to the object of type that provides that method. 为了在此对象上调用特定于DataIOPacket类的方法,编译器需要知道此指针指向提供该方法的类型的对象。 A proper way of down-casting a pointer to the polymorphic type is by using dynamic_cast , which returns NULL in case that this object can't be cast to this type: 向下转换指向多态类型的指针的正确方法是使用dynamic_cast ,如果此对象无法转换为此类型,则返回NULL

Packet* packet;
packet = new DataIOPacket();
DataIOPacket* dataIOPacket = dynamic_cast<DataIOPacket*>(packet);
if (dataIOPacket)
    dataIOPacket->getAnalogData();

Note that this is also possible with objects with automatic storage duration: 请注意,具有自动存储持续时间的对象也可以这样做:

DataIOPacket packet;
Packet* pPacket = &packet;

DataIOPacket* dataIOPacket = dynamic_cast<DataIOPacket*>(pPacket);
if (dataIOPacket)
    dataIOPacket->getAnalogData();

In this case the type of the packet is the crucial factor that decides whether dynamic_cast will succeed or not. 在这种情况下, packet的类型是决定dynamic_cast是否成功的关键因素。 The object has to be created as an instance of DataIOPacket in order to call the getAnalogData method on it. 必须将对象创建为DataIOPacket的实例DataIOPacket在其上调用getAnalogData方法。

Ok I figured out like some people suggested, that having to dynamic cast suggests my structure is wrong. 好吧我想像有些人建议的那样,不得不进行动态演员表明我的结构是错误的。 So I am going to change things that each type of packets gets it's own storage space. 所以我要改变每种类型的数据包获得它自己的存储空间的事情。 I am storing packets where I read them in and they are then passed on to a main thread that does all the processing. 我将数据包存储在我读取的位置,然后将它们传递给执行所有处理的主线程。 Indeed it makes more sense that you keep the type. 确实你保持这种类型更有意义。 My main thread doesn't want to figure out which type the packets have since it has a different way to deal with different packets. 我的主线程不想弄清楚数据包的类型,因为它有不同的方式来处理不同的数据包。 If you would ever need the behavior I described in my question I think dynamic cast is the way to go. 如果你需要我在我的问题中描述的行为,我认为动态演员是要走的路。 But before doing so you should really ask yourself if you shouldn't change the structure. 但在这样做之前,你应该问自己是否应该改变结构。 And using a dynamic cast will not work on objects since they are undergoing slicing. 并且使用动态强制转换不会对对象起作用,因为它们正在进行切片。 It only works on pointers. 它只适用于指针。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM