繁体   English   中英

多态性确定问题

[英]Polymorphism determination issue

我有一个问题,我正在努力。 我有一个数字类,在这种模式中相互继承:

#include <stdio.h>
#include <stdlib.h>

#include <list>

class TimeObject
{
  public:
    virtual void Tick()=0;

    std::list<TimeObject*> ticks;
};

class MapObject : public TimeObject
{
  public:
    MapObject()
    {
        ticks.push_front(this);

        printf("Create MapObject %p\n", this);
    }

    void Tick() { printf("mapobject tick\n"); }
};

class ControlObject : public MapObject
{
  public:
    ControlObject()
    {
        ticks.push_front(this);

        printf("Create ControlObject %p\n", this);
    }

    void Tick() { printf("controlobject tick\n"); }
};

int main()
{
    ControlObject test;

    std::list<TimeObject*>::iterator it = test.ticks.begin();

    for(; it != test.ticks.end(); it++)
    {
        TimeObject *trigger = *it;

        trigger->Tick();
    }

    return 0;
}

示例中的列表存储任何TimeObject派生类。 我的问题是,当在列表中存储也是ControlObjects MapObject指针时,调度总是选择ControlObject函数。

是否可以使用多态来使用ControlObject指针触发MapObject函数? 如果不可能/实用,什么是一个好的选择?

您应始终将指针存储到列表中的基类A*std::list< A*> )。
在将指针添加到容器之前,应该正确地指针指向类型为BC的对象。
一旦你这样做,动态调度将负责根据实际的对象类型为你调用正确的函数。 你不需要做任何事情。

我不知道为什么你想要任何其他的设计,如果你有任何理由这样做,请告诉我们。

为什么它总是在代码中调用ControlObject::tick()
你打电话时:

ticks.push_front(this); 

ControlObject::ControlObject()你最终会覆盖你添加到列表中的第一个指针,第一个推送指针的类型不再是MapObject *它是ControlObject *因为你改变了它后面的指针。你没有转移指向列表的指针的所有权,但您都拥有共享所有权,并通过派生类中的构造函数调用修改了列表中的对象。 这会在列表中留下两个ControlObject *对象,动态分派正确地确定并调用正确的方法。

动态调度没有什么问题,这是正确的行为。
如果要调用MapObject::Tick(); 那么你将明确地告诉编译器这样做,动态调度适用于实际类型的对象并且它正常工作。

void controlobject::Tick() 
{ 
    printf("controlobject tick\n"); 
    MapObject::Tick();
}

复制评论:

我担心这是一个糟糕的设计。代码工作正常,它按照C ++标准的定义。问题在于设计。除非你提供你想要在更广泛意义上实现的细节,对新设计进行推测是困难而且毫无意义的。

在类型C的变量上使用对类型B的强制转换应该可以解决问题。

   C c;
   B b;
   c.Function();
   ((B)c).Function();
   A * l[] = {&c,&b,&c};
   l[0]->Function();
   l[1]->Function();
   l[2]->Function();

   B test = *(B*)l[0];
   test.Function();

在您当前的示例中,您应该能够通过在ControlObject::Tick()调用MapObject::Tick()来调用两个虚拟成员(或者只是一个取决于底层类型的成员ControlObject::Tick()

class ControlObject : public MapObject
{
  public:
    ControlObject()
    {
        ticks.push_front(this);

        printf("Create ControlObject %p\n", this);
    }

    void Tick() { printf("controlobject tick\n"); MapObject::Tick(); }
};

显式函数调用表示法是必需的。

暂无
暂无

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

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