错误 C2280:尝试引用已删除的函数

10

我对游戏开发和C++都很陌生,但我已经开始开发一个小的打砖块游戏。之前我已经让它运行起来了,但是在重构代码(引入ArkanoidGame类)后,它无法编译,我也不知道原因。

我收到的错误信息是:

d:\dropbox\development\gamedev\c++\arkanoid\arkanoid\main.cpp(14): error C2280:
    'ArkanoidGame::ArkanoidGame(void)' : attempting to reference a deleted function
d:\dropbox\development\gamedev\c++\arkanoid\arkanoid\arkanoidgame.h(25) : 
    compiler has generated 'ArkanoidGame::ArkanoidGame' here

我只是不明白这意味着什么,也不知道该怎么做才能修复它。

我已经包含了相关的类:

Main.cpp:

#include "ArkanoidGame.h"

int main() {
    ArkanoidGame game;
    game.init(800, 600);
    while (game.isRunning()) {
        game.checkInput();
        game.checkCollisions();
        game.draw();
    }
    return 0;
}

Arkanoid.h:

#include "Ball.h"
#include "Pad.h"
#include <SFML/Graphics.hpp>
#include <stdarg.h>
#include <memory>

class ArkanoidGame
{
private:
    bool running;
public:
    void ArkanoidGame::init(int, int);
    bool ArkanoidGame::isRunning();
    void ArkanoidGame::checkCollisions();
    void ArkanoidGame::checkInput();
    void ArkanoidGame::update();
    void ArkanoidGame::draw();
    sf::RenderWindow* window;
    Pad pad;
    Ball ball;
};

弹球游戏代码文件ArkanoidGame.cpp:

#include "ArkanoidGame.h"

void ArkanoidGame::init(int windowWidth, int windowHeight) {
    window = new sf::RenderWindow(sf::VideoMode(windowWidth, windowHeight), "Arkanoid!");
    window->setFramerateLimit(60);

    ArkanoidGame::running = true;

    //Init pad
    pad = Pad((float)(windowWidth / 2), (float)(windowHeight - 50));

    //Init ball
    ball = Ball(0.f, 0.f);
}

template<class T1, class T2> bool intersect(T1& mA, T2& mB) {
    return mA.right() >= mB.left() && mA.left() <= mB.right()
        && mA.bottom() >= mB.top() && mA.top() <= mB.bottom();
}

void ArkanoidGame::checkCollisions() {
    if (!intersect(pad, ball)) return;

    ball.velocity.y = -ball.ballVelocity;

    if (ball.x() < pad.x()) {
        ball.velocity.x = -ball.ballVelocity;
    }
    else {
        ball.velocity.x = ball.ballVelocity;
    }
}

void ArkanoidGame::update() {
    //Update positions
    pad.update(window->getSize().x);
    ball.update(window->getSize().x, window->getSize().y);
}

void ArkanoidGame::draw() {
    window->clear(Color::Black);
    window->draw(pad.getShape());
    window->draw(ball.getShape());
    window->display();
}

void ArkanoidGame::checkInput() {
    if (Keyboard::isKeyPressed(Keyboard::Key::Escape)) {
        running = false;
    }
}

bool ArkanoidGame::isRunning() {
    return running;
}

1
在 Arkanoid.h 中,当成员函数在类定义内部时,您不需要使用 ArkanoidGame:: 来声明它们。 - eerorika
3个回答

14

可以推测出,Pad 或者 Ball (或者两者都有)没有默认构造函数,所以不能为包含它们的类生成默认构造函数。它们必须使用它们声明的构造函数进行初始化。

最好的解决方案是删除你奇怪的 init 函数,并用构造函数替换它:

ArkanoidGame(int windowWidth, int windowHeight) :
    running(true),
    window(new ...),
    Pad(windowWidth / 2, windowHeight - 50),
    Ball(0,0)
{
    window->setFramerateLimit(60);
}

int main() {
    ArkanoidGame game(800, 600);
    // ...
}

如果出于某种原因,您确实希望进行两阶段初始化过程,则需要为PadBall都提供默认构造函数。不过我不建议这样做;如果一个对象无法在无效状态下创建,则错误的范围就更小了。


5
我认为问题在于Pad类或Ball类中没有默认构造函数(在ArkanoidGame的类定义中有这些类的两个数据成员:Pad pad;和Ball ball;)。在这种情况下,编译器将定义ArkanoidGame类的默认构造函数为删除状态(否则它将是不合法的)。然而,在main函数的第一行中。
ArkanoidGame game;

您试图调用ArkanoidGame类的默认构造函数。

同时要注意,在类定义中,成员函数的声明应该使用未限定的名称。 例如,以下是这样的声明:

void ArkanoidGame::init(int, int);

无效。应为

void init(int, int);

3

您应该为ArkanoidGame提供一个构造函数。在Arkanoid.h文件中:

ArkanoidGame ();

在Arkanoid.cpp文件中:
ArkanoidGame::ArkanoidGame ()
{
    // it is better to initialize members in the constructor,
    // although not strictlynecessary
    running = false;
}

不完全是这样。由于其他答案中所解释的原因(PadBall,甚至两者都不具有默认构造函数),这个默认构造函数可能无法编译。 - Gorpik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接