Singleton类抛出C2653错误:不是类或名称空间名称

时间:2020-07-29 19:11:37

标签: c++ visual-studio singleton

App.h:

#ifndef APP_H
#define APP_H

#include <SFML/Graphics.hpp>
#include <vector>

#include "RoomManager.h"

typedef unsigned int uint;

class App {

private:
    sf::RenderWindow window;
    sf::Event evt;

    uint screen_width = 0;
    uint screen_height = 0;

    sf::Clock deltaClock;
    float deltaTime = 0.0f;

    RoomManager& roomManager = RoomManager::GetInstance();

    std::vector<sf::Sprite> allDrawables;

    App() { }
    ~App() { }

public:
    static App& GetInstance() {
        static App instance;

        return instance;
    }

    void CreateWindow(uint width, uint height) {
        screen_width = width;
        screen_height = height;

        window.create(sf::VideoMode(screen_width, screen_height), "Point'n'click adventure");
    }

    void Update() {
        while (window.isOpen()) {
            deltaTime = deltaClock.restart().asSeconds();

            while (window.pollEvent(evt)) {
                if (evt.type == sf::Event::EventType::Closed)
                    window.close();
            }

            Draw();
        }
    }

    void ResizeScreen(uint width, uint height) {
        screen_width = width;
        screen_height = height;

        window.setSize(sf::Vector2u(screen_width, screen_height));
    }

    void AddDrawable(sf::Sprite& sprite) {
        allDrawables.push_back(sprite);
    }

    void Draw() {
        window.clear();

        for (int i = 0; i < allDrawables.size(); i++) {
            window.draw(allDrawables[i]);
        }

        window.display();
    }
};

#endif

DrawableEntity.h:

#ifndef DRAWABLEENTITY_H
#define DRAWABLEENTITY_H

#include <SFML/Graphics.hpp>

#include "App.h"

class DrawableEntity {
private:
    sf::Texture backgroundTexture;
    sf::Sprite backgroundSprite;

public:
    DrawableEntity() {
        App::GetInstance().AddDrawable(backgroundSprite);
    }
    ~DrawableEntity() { }

    void LoadTexture(const std::string texturePath) {
        backgroundTexture.loadFromFile(texturePath);
        backgroundSprite.setTexture(backgroundTexture);
    }
};

#endif

RoomManager.h:

#ifndef ROOMMANAGER_H
#define ROOMMANAGER_H

#include <SFML/Graphics.hpp>
#include <vector>

#include "Room.h"

class RoomManager {
    private:
        std::vector<Room> rooms;

    public:
        static RoomManager& GetInstance() {
            static RoomManager instance;

            return instance;
        }

        void AddRoom(Room room) {
            rooms.push_back(room);
        }
};

#endif

Room.h:

#ifndef ROOM_H
#define ROOM_H

#include <SFML/Graphics.hpp>

#include "App.h"
#include "DrawableEntity.h"

class Room {
    private:
        DrawableEntity background;

    public:
        Room(const std::string backgroundTexturePath) {
            background.LoadTexture(backgroundTexturePath);
        }
        ~Room() { }
};

#endif

main.cpp:

#include <SFML/Graphics.hpp>

#include "App.h"

using namespace sf;

int main() {
    App& app = App::GetInstance();
    RoomManager& roomManager = RoomManager::GetInstance();

    app.CreateWindow(1920, 1080);

    roomManager.AddRoom(Room("room_0_background.jpg"));

    app.Update();

    return 0;
}

我的想法是,每当我创建DrawableEntity对象时,它都会自动将其精灵添加到App中的allDrawables向量中。上面的代码抛出C2653错误,提示“'App'不是类或名称空间名称”。错误出现在DrawableEntity()构造函数中,在我调用AddDrawable()方法的行中。自从我用C ++编码以来已经有一段时间了(现在我主要使用C#进行编码),我不确定如何解决此问题。

1 个答案:

答案 0 :(得分:0)

[注意:同样,您尚未共享 DrawableEntity()构造函数代码(我没有找到)。我假设您的问题可能是以下情况。如果以下解决方案不能解决您的问题,请共享 DrawableEntity()构造函数代码。]

您必须按如下所示调用AddDrawable():

App& appInstance = App::GetInstance();

appInstance::AddDrawable(); // it is wrong

您不应该像上面那样打电话

请执行以下操作:

App& appInstance = App::GetInstance();

appInstance.AddDrawable(); // it is correct

编辑(可能的解决方案,这必须在您的代码中发生):

我猜@drescherjm是正确的。请仔细阅读下面的代码段。我已经测试了一些类似您的代码结构的代码:

so_test.cpp文件:

#include <cstdio>
#include "so_header.h"

int main() {
    A& objA = A::getInstance();
    int xa = objA.getX();
    printf("xa: %d\n", xa);

    B& objB = B::getInstance();
    int xb = objB.getX();
    printf("xb: %d\n", xb);
    return 0;
}

so_header.h文件:

#ifndef CLASS_A

#define CLASS_A

#include <cstdio>
#include "so_header_2.h"

class A {
private:
    int x = 100;
    A(){}
public:
    static A& getInstance() {
        static A obj;
        return obj;
    }
    int getX() {
        return x;
    }
    void print() {
        B& objB = B::getInstance();
        int xb = objB.getX();
        printf("xb: %d\n", xb);
    }
};

#endif

so_header_2.h:

#ifndef CLASS_B

#define CLASS_B

#include <cstdio>
#include "so_header.h"

class B {
private:
    int x = 200;
    B(){}
public:
    static B& getInstance() {
        static B obj;
        return obj;
    }
    int getX() {
        return x;
    }
    void print() {
        A& objA = A::getInstance();
        int xa = objA.getX();
        printf("xa: %d\n", xa);
    }
};

#endif

编译so_test.cpp时,出现以下错误(使用mingw编译器):

In file included from so_header.h:6:0,
                 from so_test.cpp:2:
so_header_2.h: In member function 'void B::print()':
so_header_2.h:21:3: error: 'A' was not declared in this scope
   A& objA = A::getInstance();
   ^
so_header_2.h:21:6: error: 'objA' was not declared in this scope
   A& objA = A::getInstance();
      ^
so_header_2.h:21:13: error: 'A' is not a class, namespace, or enumeration
   A& objA = A::getInstance();

原因是在A的打印功能中,A调用了B,而在B的打印功能中,B则调用了A。

您的代码结构遵循类似的模式。让我们从DrawableEntity开始。

> DrawableEntity calls App
> App calls RoomManager
> RoomManager calls Room
> Room calls App and DrawableEntity(notice, the order here. App is called before DrawableEntity, and so loop has come back to App)
> App calls RoomManager...and ...so on...

因此,循环为:

DrawableEntity -> App -> RoomManager -> Room -> App -> RoomManager -> ...

因为,App是循环的开始或循环中第一个要调用的对象,所以在识别“ App”类时遇到了错误……原因是,您开始声明App,但从未完成声明它,并且在声明它的过程中,您正在尝试使用它。因此,您基本上是在尝试使用一种甚至还没有看到生存之光的东西(比喻可能是:它仍然在子宫里,还没有出生……)。

这与您的代码有关。

要解决您的问题,您需要稍微重新组织代码结构。只需中断呼叫依赖关系的循环(即循环),就可以了。