简体   繁体   English

处理父类对象列表时调用子类的方法

[英]Calling a Child class' method when processing a list of Parent class objects

This question seems like it might be somewhat common, but I didn't find anything when scowering StackOverflow or the interwebs. 这个问题似乎有点普遍,但是当打乱StackOverflow或互连网时我什么也没找到。

I came across a method in a C++ class that takes a list of (for example) Parent objects. 我在C ++类中遇到了一个方法,该方法采用(例如) Parent对象列表。 For this example, assume that there are two classes that derive from Parent : Child1 and Child2 . 在这个例子中,假设有从派生两类ParentChild1Child2

For each object in the list, the method checks if the object is of type Child2 (via a IsOfType() method that each class implements), and if so, it calls a method that is only provided by the Child2 class. 对于列表中的每个对象,该方法检查该对象是否为Child2类型(通过每个类实现的IsOfType()方法),如果是,则调用仅由Child2类提供的方法。

Is this an issue in that the list-processing method cannot treat each object the same? 是否存在列表处理方法不能将每个对象都相同的问题? I've seen this done in other places as well, so it seems it might be a common practice to some degree. 我在其他地方也看到过此操作,因此在某种程度上看来这可能是一种常见的做法。

One option might be to declare the Child2 method in the Parent class so that all Parent objects implement it. 一种选择是在Parent类中声明Child2方法,以便所有Parent对象都实现它。 However, in this case, only the Child2 class would actually implement any behavior when overriding the method. 但是,在这种情况下,重写方法时,只有Child2类实际上会实现任何行为。

Your thoughts? 你的意见? Thanks in advance! 提前致谢!

I think the following is a better solution for this problem. 我认为以下是解决此问题的更好方法。

class Parent {
public:
   virtual int doSomething() {}
};

class Child1 : public Parent {
};

class Child2 : public Parent {
public:
    virtual int doSomething();

Now you just omit the IsOfType call altogether and call doSomething on all of the pointers passed to you. 现在,您只需完全省略IsOfType调用,然后对传递给您的所有指针调用doSomething。

The only good reason I can think of as to why you'd have an IsOfType function is if you don't have control over the Parent class and can't modify it to add the doSomething method. 我能想到的为什么拥有IsOfType函数的唯一好理由是,如果您无法控制Parent类,并且无法修改它以添加doSomething方法。

You could declare the new method in an interface that only Child2 implements. 您可以在只有Child2实现的接口中声明新方法。 You could then use dynamic_cast<ISomeOtherInterface> to see if the object supports the extended feature. 然后,您可以使用dynamic_cast<ISomeOtherInterface>来查看对象是否支持扩展功能。 This cast will result in a null pointer for objects that don't support the additional interface. 此强制转换将为不支持附加接口的对象提供null指针。

This would allow you to create other objects that implement this feature, without requiring your list processing to know about each specific object type. 这样,您就可以创建实现此功能的其他对象,而无需列表处理来了解每种特定的对象类型。

If your IsOfType() test passes, you can cast the (pointer to the) parent object to a Child2 object and access its specific member functions. 如果您的IsOfType()测试通过,则可以将(指向)父对象强制转换为Child2对象并访问其特定的成员函数。

EDIT: This depends on your design and on how strict you ensure the IsOfType() implementation will give correct answers (ie it also works when you add new subclasses in a week). 编辑:这取决于您的设计以及确保IsOfType()实现能够给出正确答案的严格程度(即,当您在一周内添加新的子类时,它也可以工作)。 It might be safer to make use of the builtin Typeid instead. 改用内置的Typeid可能更安全。 Implementing every possible method any child would ever have in the parent would be difficult, so upcasting is ok when the method is really semantically specific to the Child2 class. 实现任何一个孩子在父级中可能拥有的所有可能的方法将很困难,因此当该方法确实在语义上特定于Child2类时,可以进行向上转换。

You might find the Visitor Pattern useful in this instance. 您可能会发现“ 访客模式”在此实例中很有用。 This will allow the objects themselves ( child1 , child2 etc) to call you back with their static type and take appropriate action. 这将允许对象本身( child1child2等)使用其静态类型回叫您并采取适当的措施。

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

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