【问题标题】:Problem with std::vector and a custom class that includes sf:: Text, C++, SFMLstd::vector 和包含 sf:: Text、C++、SFML 的自定义类的问题
【发布时间】:2021-10-03 19:49:07
【问题描述】:

我正在使用 SFML 库创建一个图形应用程序。我有一堂课,Square,它创建了一个方形块,里面有一个字母。这个类有成员 sf:: Fontsf::Text 除了正方形本身 (sf::RectangleShape)。此类的构造函数获取正方形边的大小、位置、位于项目文件夹中的字体路径以及将写入sf:: Text 的字母。该类还包含draw() 方法,该方法接受sf::RenderWindow 类型的对象并绘制正方形本身并使用它绘制文本。

问题来了。当我使用单独的变量创建一个正方形的多个实例(因此是一个带有它的字母)时,一切正常,但是当我尝试 push_back std::vector 中的正方形时,一切都中断了,错误在调试模式和发布中飞出模式只绘制小点而不是字母并且程序无法正常工作,窗口可能会停止响应 (只是正方形没有字母可以很好地与std::vector一起工作,并且它们可以正常绘制)

我认为存在与动态内存、指针或迭代器有关的错误,但我自己无法弄清楚并理解发生了什么,提前感谢您的帮助。

更好理解的代码:

class Square
{
public:
    RectangleShape m_square;
    Font m_font;
    Text m_text;

    Square(int size, Vector2f pos, string fontPath, string letter)
    {
        m_square.setFillColor(Color(0, 0, 0, 50));
        m_square.setSize(Vector2f(size, size));
        m_square.setPosition(pos);
    
        if (!m_font.loadFromFile(fontPath))
            wcout << "Error loading the font!" << endl;

        m_text.setFont(m_font);
        m_text.setFillColor(Color(0, 0, 0, 220));
        m_text.setCharacterSize(size * 0.8);
        m_text.setString(letter);
        m_text.setPosition(Vector2f((pos.x - m_text.getGlobalBounds().left) + (size - m_text.getGlobalBounds().width) / 2, pos.y));
    }   

    void draw(RenderWindow& window)
    {
        window.draw(m_square);
        window.draw(m_text);
    }

};

main.cpp:

#include <iostream>
#include <SFML/Graphics.hpp>
#include <vector>
#include <string>

#include "Square.h"

using namespace sf;
using namespace std;

int main()
{
    ContextSettings settings;
    settings.antialiasingLevel = 10;
    RenderWindow window(VideoMode(1200, 800), "My window", Style::Default, settings);
    window.setVerticalSyncEnabled(true);

    Square sq1(50, Vector2f(100, 100), "Roboto-Bold.ttf", "A");
    Square sq2(50, Vector2f(200, 100), "Roboto-Bold.ttf", "B");
    Square sq3(50, Vector2f(100, 200), "Roboto-Bold.ttf", "C");
    Square sq4(50, Vector2f(200, 200), "Roboto-Bold.ttf", "D");

    vector<Square> squares;
    squares.push_back(Square(50, Vector2f(400, 100), "Roboto-Bold.ttf", "A"));
    squares.push_back(Square(50, Vector2f(500, 100), "Roboto-Bold.ttf", "B"));
    squares.push_back(Square(50, Vector2f(400, 200), "Roboto-Bold.ttf", "C"));
    squares.push_back(Square(50, Vector2f(500, 200), "Roboto-Bold.ttf", "D"));

    while (window.isOpen())
    {
        window.clear(Color::White);

        Event event;
        while (window.pollEvent(event))
        {
            if (event.type == Event::Closed)
            {
                window.close();
            }
        }

        sq1.draw(window);
        sq2.draw(window);
        sq3.draw(window);
        sq4.draw(window);

        for (auto& s : squares)
        {
            s.draw(window);
        }

        window.display();

        if (Keyboard::isKeyPressed(Keyboard::Escape))
        {
            window.close();
        }
    }
}

这是程序的截图 window

任何帮助将不胜感激。

【问题讨论】:

  • 在编码之前开始阅读文档..Text::setFont 字体参数是指只要文本使用它就必须存在的字体。实际上,文本不存储它自己的字体副本,而是保留一个指向您传递给此函数的字体的指针。如果字体被销毁并且文本尝试使用它,则行为未定义。由于它的浅拷贝,您对字体有悬空引用 - 默认复制操作为Square
  • 使用智能指针来保存所有对象 - 避免对它们进行浅拷贝,或提供适当的操作,如复制/移动构造函数和赋值运算符。

标签: c++ vector sfml stdvector


【解决方案1】:

作为一种简单的解决方法和较小的内存和性能改进,请考虑将您的字体存储在 std::map&lt;std::string, sf::Font&gt; 中。 此数据结构允许您将字体名称映射到对象,并且它具有很好的属性,即当您添加新对象时,其中的对象不会移动。

// add this at top level
std::map<std::string, sf::Font> fonts;

// Change the Square constructor as such:
Square(int size, Vector2f pos, string fontPath, string letter) {
  if (auto it = fonts.find(fontPath); it == fonts.cend()) {
    // Font was not created before.
    auto& font = fonts[fontPath]; // this access will create a Font object and automatically store it in the map
    if (!font.loadFromFile(fontPath))
      wcout << "Error loading the font!" << endl;
  }
  ...
  m_text.setFont(fonts[fontPath]);
  ...
}

当然要删除m_font 成员。

【讨论】:

    猜你喜欢
    • 2013-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多