首页 > 解决方案 > 单例类抛出 C2653 错误:不是类或命名空间名称

问题描述

应用程序.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

可绘制实体.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

房间管理器.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

房间.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

主.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# 编码)以来已经有一段时间了,我不知道如何解决这个问题。

标签: c++visual-studiosingleton

解决方案


[注意:因为,您没有共享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,但您从未完成声明它,并且在声明它的过程中,您正在尝试使用它。因此,您基本上是在尝试使用甚至还没有看到存在之光的东西(可以类比:它仍在子宫中,尚未出生……)。

这已经发生在您的代码中。

要解决您的问题,您需要稍微重新组织您的代码结构。只需打破调用依赖的循环(即循环),就可以了。


推荐阅读