web-dev-qa-db-ja.com

エラーC2280:削除された関数を参照しようとしています

私はゲーム開発の初心者で、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;
}
10
Herter

おそらく、PadまたはBall(または両方)にはデフォルトのコンストラクターがありません。したがって、それらを含むクラスに対して生成することはできません。宣言されたコンストラクターの1つを使用して初期化する必要があります。

最善の解決策は、奇妙な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);
    // ...
}

何らかの理由で本当に2段階の初期化ダンスが必要な場合は、PadBallの両方にデフォルトのコンストラクターを提供する必要があります。それはお勧めしません。オブジェクトを無効な状態で作成できない場合、エラーの範囲が少なくなります。

14
Mike Seymour

問題は、PadクラスまたはBallクラスのいずれにもデフォルトのコンストラクターがないことだと思います(ArkanoidGameのクラス定義には、これらのクラスの2つのdtatメンバーがあります:Pad pad;およびBall ball;)。この場合、コンパイラーはクラスArkanoidGameのデフォルトのコンストラクターを削除済みとして定義しました(それ以外の場合は不正な形式になります)。ただし、メインの最初の行では

ArkanoidGame game;

arkanoidGameクラスのデフォルトのコンストラクターを呼び出そうとします。

メンバー関数の宣言は、クラス定義で非修飾名を持つ必要があることも考慮に入れてください。たとえば、この宣言は

void ArkanoidGame::init(int, int);

無効です。そうなるでしょう

void init(int, int);
5

ArkanoidGameのコンストラクタを提供する必要があります。 Arkanoid.hで:

ArkanoidGame ();

Arkanoid.cppで:

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