[英]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*>
)。
在將指針添加到容器之前,應該正確地指針指向類型為B
或C
的對象。
一旦你這樣做,動態調度將負責根據實際的對象類型為你調用正確的函數。 你不需要做任何事情。
我不知道為什么你想要任何其他的設計,如果你有任何理由這樣做,請告訴我們。
為什么它總是在代碼中調用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.