"onEachSubelement(...)" C++方法
"onEachSubelement(...)" method for C++
我经常将一些数据打包到class
中,以防止公共/全局访问出错,并提供一些常用的方法,例如:
class GameArea{
std::vector<Enemy*> enemies;
std::wstring name;
public:
void makeAllEnemiesScared();
Enemy * getEnemy(unsigned index);
};
GameArea
这里只是一个简化的例子。它是一种具有一些专门方法的自定义容器/动物园(但它不仅仅是一个容器(。
理想的情况是,当我知道将同时在每个Enemy
上执行哪些操作并且它们发生在多个位置时,因此我可以直接在GameArea
中声明它们(如makeAllEnemiesScared()
(。
对于其他情况,我可以选择:
for(unsigned i=0; i<gameArea->getEnemiesCount(); i++){
Enemy * enemy = gameArea->getEnemy(i);
...
}
但它有一些缺点:
- 我不能使用 C++11 干净漂亮的
for(auto &Enemy : enemies)
循环, - 效率不高(这么多电话
getEnemy(index)
(, getEnemy(index)
迭代抛出所有元素并不是一个目的 - 当我们想选择单个或几个元素时,它很有用,它还检查内部index < enemies.size()
- 在循环中的每个元素上检查它是很糟糕的。
注意:当我做一些非常特别的事情时,我会想到这种情况(不值得在GameArea
中创建单独的方法,而是在GameArea::enemies
的每个元素上(。
我想到了某种GameArea::onEachEnemy(... function ...)
方法,该方法将function
(或者更好的是lambda?(作为参数。这是好的解决方案吗?
或者也许这里应该使用不同的方法?就像从GameArea
归还std::vector
一样 ——这对我来说看起来有点"丑"。我不希望用户认为他实际上可以直接在该vector
中添加或删除项目。
如果你公开向量本身,或者至少是迭代器begin
和end
,你可以使用std::for_each
然后你会把它用作
std::for_each(std::begin(enemies), std::end(enemies), foo);
其中 foo 是您要在每个Enemy
上调用的函数。
再次注意,您不必公开向量本身,您可以在GameArea
中创建方法来获取迭代器,以便调用可以像
std::for_each(gameArea->GetEnemyBegin(), gameArea->GetEnemyEnd(), foo);
正如您所建议的,一个不公开类内部的好解决方案是一个为每个对象调用操作的函数:
class GameArea {
...
template<typename Func> void ForEachEnemy(Func f)
{
std::for_each(enemies.begin(), enemies.end(), f);
}
...
然后你可以传递任何你想要的东西作为参数ForEachEnemy
- 全局函数、boost::bind
结果等。
您可能需要考虑迭代器模式。这样,您可以保留封装,但仍然可以使用方便。
您可以公开标准容器迭代器,或者如果您想要完全封装,请自己编写迭代器。如果正确编写迭代器,您甚至可以使用 C++11 基于范围的 for 循环:
#include <vector>
#include <string>
#include <iostream>
struct Enemy{ std::string name; };
class EnemyIterator {
friend class GameArea;
private:
std::vector<Enemy>::iterator iterator;
EnemyIterator(std::vector<Enemy>::iterator it) : iterator(it){}
public:
EnemyIterator& operator++() { ++iterator; return *this; }
Enemy& operator*() { return *iterator; }
friend bool operator!=(EnemyIterator lhs, EnemyIterator rhs) {
return lhs.iterator != rhs.iterator;
}
};
class GameArea{
std::vector<Enemy> enemies;
public:
EnemyIterator begin() { return EnemyIterator(enemies.begin()); }
EnemyIterator end() { return EnemyIterator(enemies.end()); }
void addEnemy(std::string name) {enemies.push_back(Enemy{name}); }
};
int main() {
GameArea area;
area.addEnemy("Kobold");
area.addEnemy("Wraith");
area.addEnemy("Ork");
for (auto& enemy : area)
std::cout << enemy.name << "n";
}
为了使 C++11 基于范围的 for 循环能够与GameArea
一起使用,您需要执行以下操作之一:
- 定义开始和结束成员函数
- 在同一命名空间中定义开始和结束非成员函数 专门化标准::
- 开始和标准::结束
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 通过方法访问结构
- 最小硬币更换问题(自上而下方法)
- C++为构建时间获取QDateTime的可靠方法
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 处理多个异常集合的C++方法
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 有什么方法可以遍历结构吗
- 当类在C++中定义时,有什么方法可以"register"类吗?
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 使用std::函数映射对象方法
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- C++从另一个类访问公共静态向量的正确方法是什么
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 没有为自己的结构调用列表推回方法
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 在类定义之后定义一个私有方法
- 枚举环境变量的惯用C++14/C++17方法
- 初始化具有非默认构造函数的std::数组项的更好方法