【问题标题】:No default instructer exists for (inherited class) c++(继承的类)c ++不存在默认构造函数
【发布时间】:2018-09-07 15:55:43
【问题描述】:

程序的目的:该程序的目的是只使用控制台创建一个基本的 2d 游戏。该程序目前只创建一个带有“wasd”键的可移动框。我打算将子弹、敌方 NPC、障碍物等融入其中。

问题: 您好,由于某种原因,我的“Bullet.cpp”文件中的子弹构造函数类显示错误“错误 C2512:'BoxClass':没有适当的默认构造函数可用”。在“Bullet.h”中,我有“class Bullet : protected BoxClass”。为什么会出现此错误?

其他问题: 另外我应该如何分组我的标题?它们正在变成一个大集群。

评论: 我也意识到我的游戏循环不应该在“BoxClass.cpp”中。在我的子弹课开始工作后,我将解决这个问题。如果我的结构有任何错误,或者如果您发现编写一些相同代码的更简单方法,请告诉我。

这是我的第一个 c++ 图形游戏!

ConsolApplication1.cpp:

#include "stdafx.h"
#include <windows.h>
#include "BoxClass.h"
#include "ConsolWindow.h"
#include "Bullet.h"
#include <iostream>

using namespace std;

#define W_KEY 0x57
#define S_KEY 0x53
#define A_KEY 0x41
#define D_KEY 0x44
#define R_KEY 0x52

int main() {
    //variable declaration/definition
    int right_Wall, speed_Var;

    //Consol Size/Position
    int half_screen_Size = (GetSystemMetrics(SM_CXSCREEN)/2);
    Set_Consol_Size(half_screen_Size, GetSystemMetrics(SM_CYSCREEN));
    Position_Consol(-6, 0);

    while (1) {
        cout << "Enter speed of rectangle/box\nSpeed = ";
        cin >> speed_Var;

        BoxClass box1(4, 3);
        box1.Print_Solid_Rectangle();

        cout << "\n\nMove the rectangle with wasd\n\n";


        //Rectangle Movement
        box1.Rectangle_Movement(speed_Var);
    }
    //exit
    return 0;
}

BoxClass.cpp:

#include "stdafx.h"
#include "BoxClass.h"
#include "ConsolWindow.h"
#include <iostream>
#include <math.h>
#include <Windows.h>
using namespace std;

#define W_KEY 0x57
#define S_KEY 0x53
#define A_KEY 0x41
#define D_KEY 0x44
#define R_KEY 0x52

#define _NOT_MOVING 0
#define _MOVING 1

    //Non Moving Rectangle
    void BoxClass::Print_Solid_Rectangle() {
        //calc
        boxSpacesWidth = (3 * recWidth) - 4;

        //draw top of box
        for (width = 1; width < recWidth; width += 1) {
            cout << "...";
        }
        cout << "\n";

        //draw sides
        for (height = 1; height < recHeight; height += 1) {
            cout << ":";
            height_Count++;

            for (width = 1; width < boxSpacesWidth; width += 1) {
                cout << " ";
            }

            cout << ":\n";
        }

        //draw bottom
        cout << ":";

        for (width = 1; width < boxSpacesWidth; width += 1) {
            cout << ".";
        }
        cout << ":\n";
    }

    //Moving Rectangle
    void BoxClass::Print_Rectangle_Moving(int x, int y, int horizontalSpaces, int verticleSpaces) {
        //calc
        boxSpacesWidth = (3 * x) - 4;
        rightWall = ((x-1)*3) + horizontalSpaces;
        retrieveX = (ceil((((x-1)*3)/2))+1)+horizontalSpaces;
        retrieveY = verticleSpaces;
        cout << retrieveY<<endl;

        //New Line
        for (i = 1; i <= verticleSpaces; i += 1) {
            cout << "\n";
        }

        //draw top of box
        for (width = 1; width <= horizontalSpaces; width+=1) {
            cout << " ";
        }

        for (width = 1; width < x; width += 1) {
            cout << "...";
        }
        cout << "\n";

        //draw sides
        for (height = 1; height < y; height += 1) {

            for (width = 1; width <= horizontalSpaces; width += 1) {
                cout << " ";
            }

            cout << ":";
            height_Count++;

            for (width = 1; width < boxSpacesWidth; width += 1) {
                cout << " ";
            }

            cout << ":\n";
        }

        //draw bottom
        for (width = 1; width <= horizontalSpaces; width += 1) {
            cout << " ";
        }

        cout << ":";

        for (width = 1; width < boxSpacesWidth; width += 1) {
            cout << ".";
        }
        cout << ":\n";
    }

    void BoxClass::Rectangle_Movement(int speed) {
        speed_Var = speed;

        //Rectangle Movement
        while (GetAsyncKeyState(VK_ESCAPE) == false) {

            if (GetAsyncKeyState(R_KEY)) {
                system("CLS");
                break;
            }

            if (GetAsyncKeyState(W_KEY)) {
                if (verticleCount > 0) {
                    system("CLS");
                    verticleCount = verticleCount - speed_Var;
                    Print_Rectangle_Moving(recWidth, recHeight, horizontalCount, verticleCount);
                }
            }

            if (GetAsyncKeyState(S_KEY)) {
                system("CLS");
                verticleCount = verticleCount + speed_Var;
                Print_Rectangle_Moving(recWidth, recHeight, horizontalCount, verticleCount);
            }

            if (GetAsyncKeyState(A_KEY)) {
                if (horizontalCount > 0) {
                    system("CLS");
                    horizontalCount = horizontalCount - (speed_Var*2);
                    Print_Rectangle_Moving(recWidth, recHeight, horizontalCount, verticleCount);
                }
            }

            if (GetAsyncKeyState(D_KEY)) {
                if (rightWall < 113) {
                    system("CLS");
                    horizontalCount = horizontalCount + (speed_Var*2);
                    Print_Rectangle_Moving(recWidth, recHeight, horizontalCount, verticleCount);
                }
            }

            if (GetAsyncKeyState(VK_SPACE)) {

            }
        }
    }

    // constructor
    BoxClass::BoxClass(int x, int y) {

        //variable definition
        height_Count = 1;

        speed_Var = 1;
        horizontalCount = 0; 
        verticleCount = 0;

        recWidth = x;
        recHeight = y;
    };  

BoxClass.h:

#ifndef BOXCLASS_H
#define BOXCLASS_H


class BoxClass {
    unsigned short int width;
    int height, i, recWidth, recHeight, rightWall;
    float boxSpacesWidth, height_Count;

    int width_Var, height_Var, position_Var;
    int speed_Var = 1;
    unsigned short int horizontalCount = 0, verticleCount = 0;


protected:
    //retrieve values for bullet spawn location
    int retrieveX, retrieveY;

public:
    void Print_Rectangle_Moving(int x, int y, int horizontalSpaces, int verticleSpaces);

    void Print_Solid_Rectangle();

    void Rectangle_Movement(int speed);

    // constructor
    BoxClass(int x, int y);
};

#endif

Bullet.cpp:

#include "stdafx.h"
#include "Bullet.h"
#include <iostream>
#include <Windows.h>

using namespace std;

void Bullet::Bullet_Draw_Collision() {

    for (int height = 1; height <= 2; height+=1) {
        cout << "|\n";
    }

}



Bullet::Bullet() {
}

Bullet.h:

#ifndef BULLET_H
#define BULLET_H

#include "BoxClass.h"

class Bullet : public BoxClass {

public:
    void Bullet_Draw_Collision();

    //constructor
    Bullet();

};
#endif

ConsolWindow.cpp:

#include "stdafx.h"
#include "ConsolWindow.h"
#include <iostream>
#include <Windows.h>
using namespace std;

int Find_Consol_Size() {
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    int columns, rows;

    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
    columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
    rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;

    return columns;
}

void Set_Consol_Size(int x, int y) {
    HWND console = GetConsoleWindow();
    RECT r;
    GetWindowRect(console, &r);
    MoveWindow(console, r.left, r.top, x, y, TRUE);
}

void Position_Consol(int x, int y) {
    HWND consoleWindow = GetConsoleWindow();
    SetWindowPos(consoleWindow, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}

ConsolWindow.h:

#ifndef CONSOLWINDOW_H
#define CONSOLWINDOW_H

int Find_Consol_Size();
void Set_Consol_Size(int x, int y);
void Position_Consol(int x, int y);

#endif

【问题讨论】:

  • Bullet::Bullet() 需要调用 BoxClass 构造函数,但您没有提供。它将尝试使用默认的 BoxClass 构造函数,但没有。
  • minimal reproducible example 的示例与错误 here 重复。
  • @FrançoisAndrieux 我在哪里以及如何将我的 BoxClass 构造函数放在“Bullet::Bullet()”中?
  • @JohnathanMaxwell 请注意,在这种情况下不需要BoxClass(),它是默认行为,并且如果您根本不指定任何基本构造函数则暗示。虽然拥有它并没有错。

标签: c++ visual-studio class object visual-c++


【解决方案1】:

在 C++ 中,构造派生类型意味着必须构造对象的基部分和派生部分。这是通过在派生类型的构造函数开始之前调用基类的构造函数来完成的。

默认行为是使用基类的默认构造函数。但是,您可以通过将其添加到 member initialization list 并为其提供适当的参数来指示要使用的不同基本构造函数。

在您的情况下,请注意 BoxClass 只有一个构造函数,必须提供 xy,但 Bullet 没有这样的构造参数。也许一些默认值(例如零或一)可能是合适的,但我怀疑您可能希望将这些参数添加到您的 Bullet 类中。这里有几个例子来说明如何解决这个问题。

通过询问Bullet 的构造参数:

class Bullet : public BoxClass 
{
public:
    //constructor
    Bullet(int x, int y);

};

Bullet::Bullet(int x, int y) : 
    BoxClass(x, y) // Indicates which BoxClass constructor to use
{}

通过向BoxClass 提供任意构造参数:

class Bullet : public BoxClass 
{
public:
    //constructor
    Bullet();

};

Bullet::Bullet() : 
    BoxClass(1, 1)
{}

或者通过向 BoxClass 添加一个默认构造函数,例如为每个现有构造函数的参数赋予一个默认值:

class BoxClass 
{ 
public:
    // This constructor is now a default constructor
    BoxClass(int x = 1, int y = 1);
};

class Bullet : public BoxClass 
{
public:
    //constructor
    Bullet();

};

Bullet::Bullet() // Uses the default BoxClass constructor
{}

哪种解决方案最好取决于您的设计目标,但我怀疑第一个可能更合适。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-20
    • 2015-07-09
    • 1970-01-01
    • 2016-03-24
    • 1970-01-01
    • 2013-10-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多