C 中的视觉理解抽象
visual Understanding Abstraction in C++
从Java到C ,我正在尝试通过对象取向理解抽象。
为了将其放入一个实用的示例中,我正在使用SFML库来开发一个小型游戏。但是,这个问题与此无关,只需将其视为背景信息即可。无论如何,游戏的工作方式是通过多种不同状态进行处理。在这种情况下2:
-
菜单状态:绘制游戏的菜单,游戏将在此处开始。
-
游戏状态:此状态控制游戏,将更新实体并绘制它们。
为此,我创建了以下类:
gamestatemanager.h
#ifndef GAMESTATEMANAGER_H
#define GAMESTATEMANAGER_H
#include <SFML/Graphics.hpp>
#include <iostream>
#include "GameState.h"
class GameStateManager
{
public:
// Constructor
GameStateManager();
// State variables
static const int NUMGAMESTATES = 2;
static const int MENUSTATE = 0;
static const int GAMESTATE = 1;
// Public Functions
void set_state(int state);
void update();
void draw(sf::RenderWindow &win);
void input(sf::Event event);
private:
// Array of gamestates
GameState game_states[];
// The current state
int current_state;
// Private functions
void load_state(int state);
void unload_state(int state);
};
#endif
gamestate.h
#ifndef GAMESTATE_H
#define GAMESTATE_H
#include <iostream>
#include <SFML/Graphics.hpp>
#include "GameStateManager.h"
class GameState
{
protected:
GameStateManager gsm;
public:
virtual void init() = 0;
virtual void update() = 0;
virtual void draw(sf::RenderWindow &win) = 0;
virtual void input(sf::Event event) = 0;
};
#endif
现在,您可能已经注意到游戏州经理中的游戏阵列吗?这提供了我不理解的错误:零尺寸的数组。这是否意味着需要在标题文件中进行初始化?此外,编译器提到了一个抽象类的数组?
第二个问题是抽象游戏类中的字段GSM无法识别并提出另一个错误:缺少类型的指定词。
现在要使事情变得更复杂,我有以下课程:菜单。该课程旨在扩展游戏。
Menustate.h
#ifndef MENUSTATE_H
#define MENUSTATE_H
#include "GameState.h"
class MenuState: public GameState
{
public:
MenuState(GameStateManager gsm);
void init();
void update();
void draw(sf::RenderWindow &win);
void input(sf::Event event);
private:
sf::Texture title_texture;
sf::Sprite title_sprite;
};
#endif
如前所述,此类将控制游戏的菜单。
实现gamestateManager如下:
gamestatemanager.cpp
/*
* GameState Manager will take care of the various states of the game.
* In particular there will be two states: Menu or Ingame. GameStateManager
* will load and unload each state as needed.
*
* Author: Ben Euden
* Date: 2/5/2014
*/
#include "GameStateManager.h"
// Class Constructor
GameStateManager::GameStateManager()
{
game_states = game_states[NUMGAMESTATES];
current_state = MENUSTATE;
load_state(current_state);
}
/*
* Load the current game by creating and initialising the state
* then storing it in the game_states array.
* @Param state The state we wish to load.
*/
void GameStateManager::load_state(int state)
{
if(state == MENUSTATE)
game_states[state] = MenuState(this);
//if(state == GAMESTATE)
//game_states[state] = MainGameState(this); // Not implemented yet.
}
/*
* Unload the state we loaded with load_state
*/
void GameStateManager::unload_state(int state)
{
game_states[state] = NULL;
}
void GameStateManager::set_state(int state)
{
unload_state(state);
current_state = state;
load_state(state);
}
void GameStateManager::update()
{
try{
game_states[current_state].update();
}
catch(int e)
{
std::cout << "Exception occured during update of game state" << e << std::endl;
}
}
void GameStateManager::draw(sf::RenderWindow &win)
{
try{
game_states[current_state].draw(&win);
}
catch(int e)
{
std::cout << "Exception occured when trying to draw gamestate: " << current_state << "Exception number: " << e << std::endl;
}
}
void GameStateManager::input(sf::Event event)
{
game_states[current_state].input(event);
}
and菜单如下:
/*
* This class extends the Game State header and will deal with the menu of the game
* this includes drawing the correct text to the screen, moving the selector and
* either exiting, bringing up about or starting the game.
*
* Author: Ben Euden
* Date: 2/5/2014
*/
#include "MenuState.h"
MenuState::MenuState(GameStateManager gsm)
{
gsm = gsm;
init();
}
void MenuState::init()
{
title_texture = sf::Texture();
title_texture.loadFromFile("sprites/Title.png");
title_sprite = sf::Sprite();
title_sprite.setTexture(title_texture);
title_sprite.setPosition(512, 200);
}
void MenuState::update(){}
void MenuState::draw(sf::RenderWindow &win)
{
win.draw(title_sprite);
}
void MenuState::input(sf::Event event)
{
}
请忽略成文学的方法和位置。在这一点上,我开始尝试在错误出现时尝试编译项目(我正在使用Visual Studio)。
现在了解到尚未实施Maingamestate,但即使使用壁andate,我敢肯定,我在这里还缺少一些重要的东西,因为我仍在学习C 。考虑到这一点也请原谅任何公约等的违反,我正在学习,所以请随意纠正我,最好现在学习正确的方法,而不是养成不良习惯。
总而言之,我想理解为什么我会收到以下错误:
protected:
GameStateManager gsm;
这会产生错误:缺少';'GSM之前。
GameState game_states[];
产生以下错误的错误:零大小数组,不允许抽象类的数组。
我相信,如果我修复了其余的,那么
感谢您的耐心,时间和帮助。
euden
简而立即进行项目,并为C 初学者找到一本好书。不要试图混合您的Java知识并填补空白以达到C 知识,它将行不通,因为即使语法接近,它们也是大不相同的野兽。
无论您的背景如何,我总是建议学习C 作为一种新的和不同的语言。现在,您正在做大错误,这表明您走错了学习C 的路径。您应该回到基本教程(我不是要变得苛刻,您确实需要学习基础知识,甚至在设法编译此代码之前)。
您使用数组和成员(例如参考文献)表明您对"价值语义"和其他几个基本概念的理解不足,这些概念是C 用法中必须知道的。
例如,如果我有
class A
{
int k = 42; // C++11
};
在这里,一个对象将包含k对象。我的意思是,k不是指向int的指针,而是实际值,在分配到a对象的内存中。
所以如果我有
A my_object; // object on the stack
然后 my_object
是一个对象,以int的大小。因此,如果我这样做:
class B
{
int u;
A a;
};
然后,B的实例实际上是A
对象的大小,以及int的大小。b对象将在单个内存中包含所有这些数据。
所以当您这样做时:
class GameState
{
protected:
GameStateManager gsm;
您在这里实际做的是,您将完整的GameStateManager
构建到任何游戏对象中。是的,GSM不是参考,它是完整的对象。您应该在这里做的是使用C 参考(如果游戏经理永远不会更改)或使用指针(如果涉及所有权,则使用智能POITNER)。
我看到了许多其他问题,例如您的数组成员进入GamestateManager的含义与Java中的含义绝对不相同。基本上,您可以在此处注册C 编码。(并且您应该使用std :: vector或std ::数组,但是您的游戏模式是动态的,所以它会向量或指针数组 - 甚至是映射或其他容器)。
因为有太多要点,我应该到达核心点:
无论您以前学到的语言,甚至与C相关的C或Java,从来没有想过您对C 的了解,您绝对不知道。您需要作为初学者来处理它。将其作为一种非常新的语言学习。
,请确保您实际上阅读了列表所提供的好材料。不幸的是,在网上学习不良练习非常容易(但是它变得更好)。
另外,您可能需要阅读:https://softwareengineering.stackexchange.com/questions/questions/76675/how-can-can-a-a-java-programmer-make-make-make-the-most-the-most-a-most-a-new-project-project-IN-COR-C/76695#76695
顺便说一句,一个相关的建议:阅读" SFML游戏开发"书,例如更简单,更安全(以及C - 惯用)方法来完成您在这里尝试实现的目标。
另一面建议是避免在您的类型名称中使用"管理器",这只会使事情难以理解和设计。
the"零大小数组"错误是由GameState game_states[];
引起的。在C 中,您必须在声明时间指定数组大小,要么专门编写大小或直接初始化。
示例:
GameState game_states[ ]; // Error, compiler can't know how much memory to reserve for this.
GameState game_states[4]; // OK, explicit size given, compiler will reserve enough memory for 4 `GameState` objects.
GameState game_states[ ] = { GameState( ), GameState( ) }; // OK, direct initialization, compiler will reserve enough memory for 2 `GameState` object.
在您的情况下应该是:
GameState game_states[ NUMGAMESTATES ];
您应该从GameStateManager
构造函数中删除以下行:
game_states = game_states[NUMGAMESTATES]; // Meaningless in C++.
"不允许使用抽象类的数组"此声明也会产生,问题是C 与此处的Java不同。在C 中,此声明一个变量是一个GameState
实例,因为GameState
具有纯虚拟方法,因此不能实例化(就像Java Abstract类是new
ED一样)。为了在C 中实现这种多态性行为,您必须使用指针或参考,这是Java使用的内容。
解决此问题应该给您:
GameState * game_states[ NUMGAMESTATES ];
"缺少';'在GSM发生之前,"仅仅是因为编译器无法编译GameStateManager
,请修复我提到的错误应该解决此问题。
几个提示:
- 将C 中的变量视为Java的
int
S,即使是您声明自己的类型。这意味着它们仅通过声明然后就实例化(不需要new
),并且将它们分配给另一个变量时被复制。(默认为Java没有参考语义) - 寻找良好的C 书籍/教程,因为您似乎不了解C 的一些非常重要的基本概念。
- 无法创建抽象类的实例
- 如何定义一个纯抽象基类
- 派生类是否可以在抽象工厂设计模式中具有数据成员
- 用pybind11包装C++抽象类时出错
- 视觉studo 2019中的漫画和静态/动态绑定
- 如何改变c++应用程序的视觉效果
- 视觉工作室项目.提取源文件夹名称
- 如何处理从一个对象传递到另一个在C++中具有公共抽象类的对象的消息
- 有没有办法按值将纯抽象类的所有子类传递给 C++ 中的函数?
- 抽象类错误,请参阅声明" "是抽象的
- 将自定义函数传递到基抽象类中以延迟执行
- 为什么我在尝试模板时遇到视觉工作室C++错误
- 命名参数习惯用法和(抽象)基类
- 视觉工作室 2017;启用 /permissive 时,类型 "const wchar_t *" 的参数与类型 "PWSTR" 的参数不兼容
- 打印抽象对象 c++
- 如何在从抽象基派生的类中实现相同的方法?
- 视觉我希望一个函数在另一个函数C++中进行计算
- 将包含抽象类和普通类C++包导出到 Python
- C 中的视觉理解抽象
- 视觉 是否可以覆盖子类中的函数C++而无需对抽象的父类中的函数使用 virtual 关键字