c++ - 单例类抛出 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# 编码)以来已经有一段时间了,我不知道如何解决这个问题。
解决方案
[注意:因为,您没有共享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,但您从未完成声明它,并且在声明它的过程中,您正在尝试使用它。因此,您基本上是在尝试使用甚至还没有看到存在之光的东西(可以类比:它仍在子宫中,尚未出生……)。
这已经发生在您的代码中。
要解决您的问题,您需要稍微重新组织您的代码结构。只需打破调用依赖的循环(即循环),就可以了。
推荐阅读
- c# - 对象没有服务时间的定义
- symfony - 在同一个树枝文件中有两种不同形式的问题
- postgresql - UPSERT - INSERT ... ON CONFLICT 失败,基于函数的索引作为 'lower()' 唯一约束
- sql - 如何根据非重复列中的逻辑消除某些列中的重复项
- python - 使用 Pandas 读取带有变量类型列的 Excel
- reactjs - 我应该提到 react-native 作为我的 react-native 库的依赖项吗?
- asp.net - Why does ReturnUrl return null parameter though it shows up in the adress bar?
- c# - 本地化文件在 MVC ASP.NET Core 2.2 中无法有效呈现 Razor 页面
- c# - 在 C# 中启用/禁用脚本无法正常工作
- python - 在Python中获取文本后的数字