error C2280: attempting to reference a deleted fun

2020-07-06 02:19发布

问题:

I'm new to game development and very new to c++, but I've started developing a little Arkanoid game. I've had it running previously, but after refactoring (introducing the ArkanoidGame class) it doesnt compile and I cannot figure out why.

The error I'm getting is:

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

I simply dont understand what this means and have no idea what to do to fix it.

I've included the classes in question:

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:

Presumably, either Pad or Ball (or both) has no default constructor; therefore one can't be generated for a class that contains them. They must be initialised using one of their declared constructors.

The best solution is to remove your weird init function, and replace it with a constructor:

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);
    // ...
}

If you really want a two-stage initialisation dance for some reason, then you'll need to provide default constructors for both Pad and Ball. I wouldn't recommend that though; there's less scope for errors if an object can't be created in an invalid state.



回答2:

I think that the problem is that either class Pad or class Ball has no the default constructor ( you have two dtat members of these classes in the class definition of ArkanoidGame: Pad pad; and Ball ball;) . In this case the compiler defined the default constructor of class ArkanoidGame as deleted (otherwise it will be ill-formed). However in the first line of main

ArkanoidGame game;

you try to call the default constructor of class ArkanoidGame.

Take also into account that declarations of member functions shall have unqualified names in the class definition. So for example this declaration

void ArkanoidGame::init(int, int);

is invalid. Shall be

void init(int, int);


回答3:

You should provide a constructor for ArkanoidGame. In Arkanoid.h:

ArkanoidGame ();

In Arkanoid.cpp:

ArkanoidGame::ArkanoidGame ()
{
    // it is better to initialize members in the constructor,
    // although not strictlynecessary
    running = false;
}