C++ 错误(C2280)试图访问已删除的函数 [关闭]

Posted

技术标签:

【中文标题】C++ 错误(C2280)试图访问已删除的函数 [关闭]【英文标题】:C++ Error (C2280) tring to access a deleted function [closed] 【发布时间】:2019-03-21 19:04:07 【问题描述】:

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

#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;

我搜索了微软文档和其他 *** 问题,但找不到像我这样的案例,希望有人能提供帮助,谢谢

【问题讨论】:

请附上完整的错误信息 请将编译器的完整错误信息添加到您的帖子中。 sf::RenderWindow 的基类是sf::Window,它派生自NonCopyable。您不能将 RenderWindow 按值传递给 Button::render。看diagram。使用参考。 不是问题,但你的析构函数会使你的程序崩溃。你只在你打电话给new的事情上打电话给delete。你不要在班级成员上调用new,所以你不应该在他们身上调用delete 我真的怎么强调都不过分。不要使用 sfml 将您的第一个程序变成游戏!实在是太消化不了了!学习使用更简单的主题在 C++ 中编程,比如可能是文本处理或小型数据管理器或类似的东西。尝试实现一个科学计算器或其他不会让您接触到庞大而复杂的库的东西。基本上,你需要在练习潜水之前学习如何游泳——尽管潜水可能更有趣。 【参考方案1】:

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

这样的函数签名中
void Button::render(sf::RenderWindow window);

您正在接受sf::RenderWindow 按价值。这意味着每当您调用Button::render 并传递一个窗口时,该窗口在被函数接收之前复制。看到问题了吗?

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

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

除此之外:正如 NathanOliver 所指出的,您尝试在 Button 析构函数中使用 delete 所有实例成员,即使它们不是指针,并且您没有专门使用 new 分配它们。只有deletenew,如果可以的话,完全避免new/delete

如果您不确定通过引用传递的含义,或者不确定newdelete 的用途,我建议您获取一份good C++ book 的副本。

【讨论】:

哦,谢谢,只是想让你知道我是 C++ 新手,所以我知道我做了一些愚蠢的代码【参考方案2】:

首先。什么...

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)

【讨论】:

以上是关于C++ 错误(C2280)试图访问已删除的函数 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Visual Studio 2013 和 2015 中的 C++ 编译器错误 C2280“试图引用已删除的函数”

C++错误C2280 - 试图引用一个已删除的函数 - 在基元类型上。

编译器错误 C2280,试图引用已删除的函数 operator=

试图找到已删除的函数

PlatformToolset 和“已删除功能”错误 (C2280)

对复制构造函数已被删除的对象向量进行迭代 (C2280)