Calling a method from an iterator

93 views Asked by At

I need to call a method from something that has been stored inside of an std::list. Currently, the loop runs and the print inside prints to the console, but the elements inside the list do not actually print what they are supposed to. Here are the relevant files:

#include "TextWindow.hpp"
#include "TextElement.hpp"

#include <iostream>
TextWindow::TextWindow(const TextureHolder& textures, const FontHolder& fonts, sf::Window& windows, Fonts::ID fontID, sf::String text)
: mSprite(textures.get(Textures::WindowDefault))
, mHitpoints(10)
, mWindow(windows)
{
    sf::FloatRect bounds = mSprite.getLocalBounds();
    mSprite.setOrigin(bounds.width / 2.f, bounds.height / 2.f);
    addElements(text, fonts.get(fontID));
}

void TextWindow::addElements(sf::String text, sf::Font font)
{
    TextElement e(text, font, 10, xPos, yPos, 10, 10);
    mElements.push_back(e);
}

void TextWindow::drawCurrent(sf::RenderTarget& target, sf::RenderStates states) const
{
    target.draw(mSprite, states);
    for(std::list<Element>::const_iterator iterator = mElements.begin(); iterator != mElements.end(); ++iterator)
    {
        //std::cout << "IN TEXTWINDOW PRINT ITERATOR" << std::endl;
        (*iterator).drawCurrent(target, states);
    }

}

void TextWindow::updateCurrent(sf::Time dt)
{
}

And

#include "TextElement.hpp"
#include <iostream>

TextElement::TextElement(sf::String text, sf::Font font, int textSize, int xOrig, int yOrig, int xPos, int yPos)
: mText(text, font, textSize)
, xpos(xPos)
, ypos(yPos)
{
    mText.setOrigin(xOrig, yOrig);
    mText.setColor(sf::Color::Green);
}

void TextElement::drawCurrent(sf::RenderTarget& target, sf::RenderStates states) const
{
    std::cout << "TEXTELEMENT" << std::endl;
    target.draw(mText, states);
}
void TextElement::updateCurrent(sf::Time dt)
{
    //Do nothing, text doesn't need to update!
}

Any suggestions?

EDIT: After changing the list to std::unique_ptr, I get the following error:

1>------ Build started: Project: Byte, Configuration: Debug Win32 ------
1>  TextWindow.cpp
1>e:\gamedev\c++\byte\byte\textwindow.cpp(19): error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'
1>          with
1>          [
1>              _Ty=Element
1>          ]
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\memory(2350) : see declaration of 'std::unique_ptr<_Ty>::unique_ptr'
1>          with
1>          [
1>              _Ty=Element
1>          ]
1>  Generating Code...
1>  Compiling...
1>  Generating Code...
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

I have changed all references to the variable to std::unique_ptr. Here are the new files:

#include "TextWindow.hpp"
#include "TextElement.hpp"

#include <iostream>

TextWindow::TextWindow(const TextureHolder& textures, const FontHolder& fonts, sf::Window& windows, Fonts::ID fontID, sf::String text)
: mSprite(textures.get(Textures::WindowDefault))
, mHitpoints(10)
, mWindow(windows)
{
    sf::FloatRect bounds = mSprite.getLocalBounds();
    mSprite.setOrigin(bounds.width / 2.f, bounds.height / 2.f);
    addElements(text, fonts.get(fontID));
}

void TextWindow::addElements(sf::String text, sf::Font font)
{
    std::unique_ptr<TextElement> e(new TextElement(text, font, 10, xPos, yPos, 10, 10));
    mElements.push_back(e);
}

void TextWindow::drawCurrent(sf::RenderTarget& target, sf::RenderStates states) const
{
    target.draw(mSprite, states);
    for(std::list<std::unique_ptr<Element>>::const_iterator iterator = mElements.begin(); iterator != mElements.end(); ++iterator)
    {
        //std::cout << "IN TEXTWINDOW PRINT ITERATOR" << std::endl;
        (*iterator).get()->drawCurrent(target, states);
    }

}

void TextWindow::updateCurrent(sf::Time dt)
{
}
1

There are 1 answers

3
Jonathan Potter On BEST ANSWER

From what you've posted above, it looks like mElements is a std::list<Element>, and I'm assuming TextElement inherits from a virtual base class Element.

This won't work. mElements will only store Element objects, not derived objects - this is known as the slicing problem.

You need to change mElements to std::list<unique_ptr<Element>> (or shared_ptr) so that the whole object can be stored in the list.