2016-02-13 113 views
1

从基类中覆盖函数有点麻烦。从基类覆盖函数

这是我的游戏对象类:

namespace GameEngine { 
    class GameObject { 
    public: 
     virtual void render() { 
      std::cout << "Render Game Object" << std::endl; 
     } 
    }; 
} 

这是我的播放器类:

class Player : public GameEngine::GameObject { 
public: 
    void render() { 
     std::cout << "Render Player" << std::endl; 
    } 
}; 

在MainComponent.cpp我有GameObjects的载体,和我遍历它们,使它们

Player player; 
vector<GameEngine::GameObject> gameObjects; 

void MainComponent::init() { 
    gameObjects.push_back(player); 

    gameLoop(); 
} 

void MainComponent::render() { 
    for(int i = 0; i < gameObjects.size(); i++) { 
     gameObjects[i].render(); 
    } 
} 

我希望这段代码输出“渲染播放器”,因为gameObjects中的唯一对象ctor是播放器,但是它输出“渲染游戏对象”。有没有一种方法可以强制GameObject向量中的Player对象使用Player渲染器而不是GameObject渲染器?

+0

这与重载无关。 'Player :: render' **覆盖**'GameObject :: render'。 –

+0

@PeteBecker你说得对,我的错误,我编辑的职位,以反映这一点。 – shadowarcher

回答

2

如果一个派生类使用指针或引用到基部 类处理,在重写虚拟函数的调用将调用在派生类中定义的 行为。

您必须将指向基类的指针而不是基对象值存储到向量中。

Player player; 
vector<GameEngine::GameObject*> gameObjects; 

void MainComponent::init() { 
    gameObjects.push_back(&player); 

    gameLoop(); 
} 

void MainComponent::render() { 
    for(int i = 0; i < gameObjects.size(); i++) { 
     gameObjects[i]->render(); 
    } 
} 
1

下面是说明了同样的问题的代码的简化版本:

GameEngine::GameObject object = player; 
object.render(); 

问题是player对象通过切掉player的基本部分而被转换为GameObject。所以存储的是GameObject,而不是Player对象。

的解决方案是使用指针或引用,而不是一个对象:

GameEngine::GameObject *ptr = &player; 
ptr->render(); 

你需要做同样的事情在gameObjects:而不是存储GameObject应该指针存储GameObject类型的对象:

std::vector<GameEngine::GameObject*> gameObjectPointers; 
gameObjectPointers.push_back(&player); 
gameObjectPointers[0]->render(); 

一旦你这样做,你必须密切关注对象的生命周期。如果playergameObjectPointers之前被破坏,则gameObjectPointers[0]指向一个不再存在的对象,并且使用它将使不好的事情发生。

1

有没有一种方法可以强制GameObject向量中的Player对象使用Player渲染器而不是GameObject渲染器?

No.你跟vector<GameEngine::GameObject> gameObjects;类型声明vector,所以基类的实例将被存储在vector。而当gameObjects.push_back(player);,对象将是slicing copied,没有Player

您可以将基类指针到vector,并更好地使用智能指针,以避免手动内存管理CHINESE。例如:

vector<unique_ptr<GameEngine::GameObject>> gameObjects; 

void MainComponent::init() { 
    gameObjects.emplace_back(new Player); 
    // or gameObjects.push_back(unique_ptr(new Player)); 
    gameLoop(); 
} 

void MainComponent::render() { 
    for(int i = 0; i < gameObjects.size(); i++) { 
     gameObjects[i]->render(); 
    } 
}