【问题标题】:C++ Vector iterate over abstract classC++ Vector 遍历抽象类
【发布时间】:2012-05-13 19:42:00
【问题描述】:

背景信息: 我和几个朋友在 och sfml 和 box2d 的帮助下用 C++ 构建这个平台游戏,用于学校作业。 要求之一是我们遵循“MVC 模式”。

我们为模型创建了 Bullet 和 Character 等类。以及视图的 BulletView 和 CharacterView(都继承了抽象类 sf::Drawable)。

而不是重复绘制代码,并且有两个方法drawBullets和drawCharacter这样

void WorldView::drawBullets()
{
    std::vector<BulletView*>::iterator it;
    for ( it = bullets.begin() ; it < bullets.end(); it++ )
        window->draw(**it);
}

void WorldView::drawCharacters()
{
    std::vector<CharacterView*>::iterator it;
    for ( it = characters.begin() ; it < characters.end(); it++ )
        window->draw(*it);
}

我想要一个使用多态的更通用的方法,看起来像这样:

void WorldView::drawVector(const std::vector<sf::Drawable*>& vector)
{
    std::vector<sf::Drawable*>::iterator it;
    for ( it = vector.begin() ; it < vector.end(); it++ )
        window->draw(**it);
}

bulletView 向量声明如下:

std::vector<BulletView*> bullets;

虽然不能让它工作。我对 C++ 有点陌生,所以请怜悯!我试过搜索,但没有找到非常具体的答案。

我在编译时遇到的错误。

错误 8 错误 C2679:二进制“=”:未找到采用“std::_Vector_const_iterator<_myvec>”类型的右手>操作数的运算符(或没有可接受的>转换)c:\users\niklas \multiplaya\sfml test\sfml test\view\worldview.cpp 409 >1 SFML_Test

错误 7 错误 C2664: 'mp::WorldView::drawVector' : 无法将参数 1 从 >'std::vector<_ty>' 转换为 'const std::vector<_ty> &' c:\users\ niklas\multiplaya\sfml >test\sfml test\view\worldview.cpp 402 1 SFML_Test

【问题讨论】:

  • std::vector bullets; 不是一个有效的声明:向量的模板类型是什么?
  • @Autopulated 这是一个格式问题,我已修复。

标签: c++ vector iterator sfml


【解决方案1】:

问题是多态性在向量级别不起作用,而是在它们包含的指针级别起作用。所以std::vector&lt;Derived*&gt; 永远不能作为std::vector&lt;Base*&gt; 传递,因为它们是完全不同的类型。但是,您可以使用指向 Derived* 的指针填充 std::vector&lt;Base*&gt;

所以,你应该将你的子弹矢量声明为

std::vector<Drawable*> bullets;

并填写BulletView*,例如:

bullets.push_back( new BulletView( some args) );

drawVector(bullets);

注意:在上面的代码中,我回避了动态分配对象所有权的问题。显然,必须有某种机制在适当的时候删除BulletViews

【讨论】:

  • 嗯,好吧。然后我可能会用类似“GameObjectView”类的东西来继承 sf::Drawable 类。感谢您的回答!
【解决方案2】:

不要使用多态向量,而是使用模板函数:

template <typename T>
void WorldView::drawVector(const std::vector<T*>& vector)
{
    typename std::vector<T*>::iterator it;
    for ( it = vector.begin() ; it < vector.end(); it++ )
        window->draw(**it);
}

顺便说一句 - 原始指针向量对我来说看起来很可疑。谁拥有它们(谁创建它们以及谁负责删除它们)?考虑使用值向量或boost::ptr_vector

【讨论】:

    【解决方案3】:

    您遇到的错误是由 it = vector.begin(); 循环中的分配 for 产生的。问题是您试图将iterator(it) 分配给const iterator(vector.begin())。您不能使用 const 迭代器迭代数据结构,因为它的值在每次迭代时都会发生变化。此外,在使用迭代器遍历数据结构时,您应该使用 operator != 而不是 operator &lt;

    如果您从const std::vector&amp; vector 中删除const,则一切正常。

    希望这会有所帮助!

    【讨论】:

    • 谢谢!不过,问题似乎是@juanchopanza 之前所说的。
    【解决方案4】:

    你在模仿Composite Design-Pattern

    但是您的错误是:您应该编写 replaceing 因为它是 iterator 而不是 int

    void WorldView::drawBullets()
    {
        std::vector<BulletView*>::iterator it;
        for ( it = bullets.begin() ; it != bullets.end(); it++ )
            window->draw(**it);
    }
    
    void WorldView::drawCharacters()
    {
        std::vector<CharacterView*>::iterator it;
        for ( it = characters.begin() ; it != characters.end(); it++ )
            window->draw(*it);
    }
    I would like a more generic method using polymorhism which would look something like this:
    
    void WorldView::drawVector(const std::vector<sf::Drawable*>& vector)
    {
        std::vector<sf::Drawable*>::iterator it;
        for ( it = vector.begin() ; it != vector.end(); it++ )
            window->draw(**it);
    }
    

    【讨论】:

    • vector有随机访问迭代器,可以和operator&lt;比较
    猜你喜欢
    • 2018-11-26
    • 1970-01-01
    • 2021-07-28
    • 2020-08-26
    • 1970-01-01
    • 1970-01-01
    • 2019-04-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多