-1

所以,我试图用 opengl 和 sfml 制作一个 2d 游戏,所以我在输入命名空间中创建了一个按钮类,我在其中创建了一个 render() 函数,但是当我调用它时(无论我使用指针还是我没有)即使我传递了所有必需的参数,它仍然给我一个错误,说我正在尝试访问一个已删除的函数,这是 Button 标题:

#pragma once

#include <SFML/Graphics.hpp>
#include "InputManager.h"

namespace input {

class Button {
private:
    bool m_Selected, m_Clicked;
    sf::Vector2f m_Position;
    sf::Sprite m_Sprite;
    sf::Texture m_Texture;
public:
    Button(sf::Vector2f position, sf::Sprite sprite);
    Button(sf::Vector2f position, sf::Texture texture);
    Button(sf::Vector2f position);
    Button();
    ~Button();
    void update(engine::InputManager inputManager);
    void render(sf::RenderWindow window);
    inline bool isClicked() { return m_Clicked; }
    inline bool isSelected() { return m_Selected; }
    inline sf::Vector2f getPosition() { return m_Position; }
    void setPosition(sf::Vector2f position) { m_Position = position; }
};

}

这是 Button.cpp:

#include "Button.h"

namespace input {

Button::Button(sf::Vector2f position, sf::Sprite texture) : m_Position(position), m_Sprite(texture) {
    m_Sprite.setPosition(m_Position);
}

Button::Button(sf::Vector2f position, sf::Texture texture) : m_Position(position), m_Texture(texture) {

    m_Sprite.setTexture(m_Texture);
    m_Sprite.setPosition(m_Position);
}

Button::Button(sf::Vector2f position) : m_Position(position) {
    m_Sprite.setPosition(m_Position);
}

void Button::update(engine::InputManager inputManager) {}

void Button::render(sf::RenderWindow window) {
    window.draw(m_Sprite);
}

Button::~Button() {
    delete &m_Position;
    delete &m_Texture;
    delete &m_Clicked;
    delete &m_Selected;
}
}

这是 main.cpp 代码:

#include <iostream>
#include <vector>
#include "InputManager.h"
#include "Button.h"

#define WIDTH 800
#define HEIGHT 600
#define TITLE "C++ Platformer"

int main() {

sf::RenderWindow window(sf::VideoMode(WIDTH, HEIGHT), TITLE, sf::Style::Close | sf::Style::Titlebar);

sf::Texture ButtonTexture;
ButtonTexture.loadFromFile("Texture.png");
sf::Sprite sprite;
sprite.setTexture(ButtonTexture);

input::Button* button = new input::Button(sf::Vector2f(100.f, 100.f), sprite);

int fps = 0;

int ticks = 0;

sf::Clock clock;
sf::Clock FpsClock;
sf::Time time;
sf::Time Fpstime;

long delta = 0;
long target = 1000000 / 60;

engine::InputManager IManager;

sf::Event ev;
while (window.isOpen()) {
    while (window.pollEvent(ev)) {
        if (ev.type == sf::Event::Closed) window.close();
        if (ev.key.code == sf::Keyboard::Escape) window.close();
        if (ev.type == sf::Event::KeyPressed) IManager.onKeyDown(ev.key.code);
    }
    time = clock.getElapsedTime();
    if (target > time.asMicroseconds()) {
        clock.restart();
        // UPDATE
        button->update(IManager);

        delta = time.asMicroseconds() % 60;
        target = 1000000 / 60 + delta;
        ticks++;
    } Fpstime = FpsClock.getElapsedTime();
    if (Fpstime.asSeconds() >= 1) { 
        std::cout << "FPS: " << fps << " Ticks: " << ticks << std::endl; 
        FpsClock.restart();
        fps = 0;
    }
    fps++;
    // RENDER
    button->render(window);
}

return EXIT_SUCCESS;
}

我已经搜索了 microsoft docs 和其他 stackoverflow 问题,但我找不到像我这样的案例,希望有人能提供帮助,谢谢

4

2 回答 2

3

首先。什么...

Button::~Button() {
    delete &m_Position;
    delete &m_Texture;
    delete &m_Clicked;
    delete &m_Selected;
}

你不应该那样做。

但回到你的错误。它非常具有描述性。您正在尝试使用最有可能被明确删除的函数。像这样:

struct Test {
    Test(const Test & other) = delete; 
};

显然我现在无法复制Test,因为我删除了复制构造函数。

这就是sf::RenderWindow通过继承sf::NonCopyable类所做的。

而且由于您的render()方法通过复制而不是引用来获取它。它显然试图做一些它被禁止的事情。

你应该改变这个:

void Button::render(sf::RenderWindow window)

对此:

void Button::render(sf::RenderWindow & window)
于 2019-03-21T19:14:09.097 回答
3

问题是这sf::RenderWindow是不可复制的。这是一件好事,因为这意味着您不会意外地对拥有多个窗口感到困惑,并且在您创建新窗口时以及它的拥有位置是很清楚的。但是,在函数签名中

void Button::render(sf::RenderWindow window);

您正在接受sf::RenderWindow by value。这意味着无论何时调用Button::render并传递一个窗口,该窗口都会在函数接收到它之前被复制。看到问题了吗?

您需要通过引用接受渲染窗口,以确保您不尝试创建副本:

void Button::render(sf::RenderWindow& window);

另外:正如 NathanOliver 所指出的,您尝试delete在析构函数中使用所有实例成员Button,即使它们不是指针,并且您没有专门为它们分配new. 只做delete你自己new,尽可能避免new/delete完全避免。

如果您不确定通过引用传递是什么意思,或者不确定是为了什么newdelete我建议您选择一本好的 C++ 书籍

于 2019-03-21T19:14:31.243 回答