gpt4 book ai didi

c++ - 存储所有类实例的 vector ,并调用它们的成员函数

转载 作者:行者123 更新时间:2023-11-27 23:55:16 36 4
gpt4 key购买 nike

如何创建一个存储类的所有实例的 vector ?那么我该如何遍历它们并调用它们的成员函数之一呢?

这是我一直在尝试做的事情的浓缩示例。

#include <vector>

struct Entity{

Entity::Draw(){
// do drawing things
}
};

static std::vector<Entity> entities;

Entity player;
Entity enemy;

void renderEntities() {

for (std::vector<Entity>::iterator iter = entities.begin();
iter < entities.end();
iter++) {

iter->Draw; // Error in the example. I'm using Draw(); in the actual code.
}

但是 renderEntities() 没有做任何事情。 Draw 成员函数有效,如果我使用例如播放器->绘制。我要么搞砸了 vector 或迭代器,要么两者都搞砸了,我不知道如何修复它。我尝试过使用引用和指针,我认为这是应该做的事情,但每当我尝试这样做时,我都会遇到无法修复的错误。

更新:我感谢所有的帮助,我学到了很多东西。但是我的 render_entities 函数仍然没有做任何事情。这是所有代码。

任何以 terminal_ 开头的函数调用都来自 BearLibTerminal 库。

主要.cpp

#include <BLT/BearLibTerminal.h>
#include <iostream>
#include <string.h>
#include <vector>

#include "entity.h"

const int WindowSizeX{50};
const int WindowSizeY{20};
const std::string Title{"BLT Test"};
const std::string Font{"../res/SourceCodePro-Regular.ttf"};
const int FontSize{24};

bool quit_game{false};

static Entity player;
static Entity enemy;

void initialize();
void handle_input(int key, Entity &entity);
void draw_player(int x, int y, const char *symbol);
void render_entities();
void clear_entities();

int main() {

initialize();

while (!quit_game) {

terminal_refresh();

int key{terminal_read()};

if (key != TK_CLOSE) {

handle_input(key, player);
}

else {

quit_game = true;
break;
}

clear_entities();
}

terminal_close();

return 0;
}

void initialize() {

terminal_open();

std::string size{"size=" + std::to_string(WindowSizeX) + "x" +
std::to_string(WindowSizeY)};
std::string title{"title='" + Title + "'"};
std::string window{"window: " + size + "," + title};

std::string fontSize{"size=" + std::to_string(FontSize)};
std::string font{"font: " + Font + ", " + fontSize};

std::string concatWndFnt{window + "; " + font};
const char *setWndFnt{concatWndFnt.c_str()};

terminal_set(setWndFnt);
terminal_clear();

player.x = 0;
player.y = 0;
player.layer = 0;
player.symbol = "P";
player.color = "green";

enemy.x = 10;
enemy.y = 10;
enemy.layer = 0;
enemy.symbol = "N";
enemy.color = "red";
}

void handle_input(int key, Entity &entity) {

int dx{0};
int dy{0};

switch (key) {

case TK_LEFT:
case TK_H:
dx = -1;
dy = 0;
break;

case TK_RIGHT:
case TK_L:
dx = 1;
dy = 0;
break;

case TK_UP:
case TK_K:
dx = 0;
dy = -1;
break;

case TK_DOWN:
case TK_J:
dy = 1;
dx = 0;
break;

case TK_Y:
dx = -1;
dy = -1;
break;

case TK_U:
dx = 1;
dy = -1;
break;

case TK_B:
dx = -1;
dy = 1;
break;

case TK_N:
dx = 1;
dy = 1;
break;

case TK_ESCAPE:
quit_game = true;
break;
}

player.Move(dx, dy);

if (player.x > WindowSizeX - 1) {

player.x = WindowSizeX - 1;
}
else if (player.x < 0) {

player.x = 0;
}

if (player.y > WindowSizeY - 1) {

player.y = WindowSizeY - 1;
}
else if (player.y < 0) {

player.y = 0;
}

player.Draw(); // This works.
enemy.Draw(); // So do this.
entity.Draw(); // This draws only player.
render_entities(); // This doesn't do anything.

// Player X and Y are printed out correctly, Entities is always 0.
std::cout << "Player X: " << player.x << std::endl;
std::cout << "Player Y: " << player.y << std::endl;
std::cout << "Entities: " << entities.size() << std::endl;
}

void render_entities() {

for (auto entity : entities) {
entity->Draw();
}
}

void clear_entities() {

for (auto entity : entities) {
entity->Clear();
}
}

实体.h

#ifndef ENTITY_H_
#define ENTITY_H_

struct Entity {

int x;
int y;
int layer;
const char *symbol;
const char *color;

Entity();
~Entity();

void Move(int dx, int dy);
void Draw();
void Clear();
};

static std::vector<Entity *> entities;

#endif /* ENTITY_H_ */

实体.cpp

#include <BLT/BearLibTerminal.h>
#include <vector>
#include <algorithm>
#include "entity.h"

Entity::Entity() {

entities.push_back(this);
}

// Entity(const Entity &) : Entity() {}
// I get an "expected unqualified-id" when I uncomment this. Why?

Entity::~Entity() {

auto iter = std::find(entities.begin(), entities.end(), this);

if (iter != entities.end())
entities.erase(iter);
}

void Entity::Move(int dx, int dy) {

this->x += dx;
this->y += dy;
}

void Entity::Draw() {

terminal_layer(this->layer);
terminal_color(color_from_name(this->color));
terminal_print(this->x, this->y, this->symbol);
}

void Entity::Clear() {

terminal_layer(this->layer);
terminal_print(this->x, this->y, " ");
}

在 main.cpp 中,在 handle_input() 的底部你会看到......

    player.Draw(); // This works.
enemy.Draw(); // So do this.
entity.Draw(); // This draws only player.
render_entities(); // This doesn't do anything.

// Player X and Y are printed out correctly, Entities is always 0.
std::cout << "Player X: " << player.x << std::endl;
std::cout << "Player Y: " << player.y << std::endl;
std::cout << "Entities: " << entities.size() << std::endl;

最佳答案

renderEntities() 不执行任何操作,因为您没有将任何 Entity 对象添加到 vector。当您声明您的 playerenemy 对象时,它们只是停留在内存中,不会自动添加到 vector 中。您需要显式添加它们,例如通过调用 entities.push_back()

我建议使用 Entity 构造函数和析构函数自动更新 vector,而不必记住手动执行。这样,每个 Entity 对象都由 renderEntities() 负责,例如:

#include <vector>
#include <algorithm>

struct Entity;
static std::vector<Entity*> entities;

struct Entity
{
Entity()
{
entities.push_back(this);
}

Entity(const Entity &)
: Entity()
{
}

~Entity()
{
auto iter = std::find(entities.begin(), entities.end(), this);
if (iter != entities.end())
entities.erase(iter);
}

void Draw()
{
// do drawing things
}
};

Entity player;
Entity enemy;

void renderEntities()
{
for (auto *entity : entities)
{
entity->Draw();
}
}

Live Demo


更新:在看到你的完整代码后,我发现你仍然犯了一些错误。

main.cpp中,handle_input()作用域内没有entity变量,所以调用entity.Draw( ) 不应编译。

不过,真正大的错误是在 entity.h 中。不要在该文件中将您的 entities 变量声明为 static!这会导致每个 .cpp #include 是您的entity.h 文件变量的拷贝。这意味着 main.cppentity.cpp单独的 std::vector 对象 上运行!这就是为什么您在 main.cpp 中看到 entities 总是空的 - Entity 对象永远不会被添加到 std::存在于main.cpp中的vector,只对应于存在于entities.cpp中的std::vector

您需要将实际的 std::vector 变量移动到 entity.cpp(没有 static),然后将变量声明为entity.h 中的 extern 以便您的所有 .cpp 文件都可以访问和共享该单个变量

试试这个:

实体.h

#ifndef ENTITY_H_
#define ENTITY_H_

#include <vector>
#include <string>

struct Entity {
int x = 0;
int y = 0;
int layer = 0;
std::string symbol;
std::string color;

Entity();
Entity(const Entity&);
~Entity();

Entity& operator=(const Entity&) = default;

...
};

extern std::vector<Entity *> entities; // <-- extern, NOT static!

#endif /* ENTITY_H_ */

实体.cpp

#include <BLT/BearLibTerminal.h>
#include <vector>
#include <algorithm>
#include "entity.h"

std::vector<Entity *> entities; // <-- real variable, also NOT static!

Entity::Entity() {
entities.push_back(this);
}

Entity::Entity(const Entity &src) : Entity() {
*this = src;
}

Entity::~Entity() {
auto iter = std::find(entities.begin(), entities.end(), this);
if (iter != entities.end())
entities.erase(iter);
}

...

void Entity::Draw() {
terminal_layer(layer);
terminal_color(color_from_name(color.c_str()));
terminal_print(x, y, symbol.c_str());
}

...

关于c++ - 存储所有类实例的 vector ,并调用它们的成员函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50731378/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com