Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何通过保持性能来管理封装_C++_C++11_Inline_Encapsulation - Fatal编程技术网

C++ 如何通过保持性能来管理封装

C++ 如何通过保持性能来管理封装,c++,c++11,inline,encapsulation,C++,C++11,Inline,Encapsulation,我正试图找出以下问题的最佳解决方案: 我有一个管理游戏图形的库(不能直接修改)。我有一个实体类,它是可显示实体的逻辑实体,该实体由一个精灵实例配对 图形库已经包含了管理sprite集合的支持,因此我甚至希望在不让逻辑知道图形引擎的情况下使用它(我不希望包含标题),以实现与迭代实体相关的所有目的(其中有许多需要每秒多次更新) 为了在保留封装的同时获得此解决方案,我想出了一个与此类似的解决方案(我将其过于简化): gfx_engine.h(不可修改) 实体.h #include "gfx_engin

我正试图找出以下问题的最佳解决方案:

我有一个管理游戏图形的库(不能直接修改)。我有一个
实体
类,它是可显示实体的逻辑实体,该实体由一个
精灵
实例配对

图形库已经包含了管理sprite集合的支持,因此我甚至希望在不让逻辑知道图形引擎的情况下使用它(我不希望包含标题),以实现与迭代实体相关的所有目的(其中有许多需要每秒多次更新)

为了在保留封装的同时获得此解决方案,我想出了一个与此类似的解决方案(我将其过于简化):

gfx_engine.h(不可修改)

实体.h

#include "gfx_engine.h"

class EntitySprite : public Sprite
{
private:
  Entity *entity;

public:
  ...
  void setEntity(Entity* entity) { this->entity = entity; }
  Entity* getEntity() { return entity; }
};
class SpriteBatch;

template<typename T>
class EntityCollection
{
private:
  SpriteBatch* batch;

public:
  class const_iterator
  {
  private:
    std::vector<Sprite*>::const_iterator inner;

  public:
    const_iterator(const std::vector<Sprite*>::const_iterator& it) : inner(it) { }

    inline bool operator!=(const const_iterator& other) const { return inner != other.inner; }
    inline const const_iterator& operator++() { ++inner; return *this; }
    T* operator*() const;
  };

  const_iterator begin() const;
  const_iterator end() const;

  EntityCollection() : batch(nullptr) { }
  explicit EntityCollection(SpriteBatch* batch) : batch(batch) { }
};

有什么建议吗?

只需将
EntitySprite.h
放在标题中,然后就可以使用它了。唯一的缺点是编译时间稍长。 如果编译时间对开发很重要,那么您可以使用
#ifdef NDEBUG
以两种方式进行编译:一种方式在声明(头文件)中,另一种方式在实现文件(cpp)中


在声明文件和定义文件之间分离的传统
c
中,这是一个巨大的问题。在其他语言中,一切都在一个文件中,编译器/链接器会为您进行排序(即c#)。

您尝试过链接时间优化(LTO)吗?一些编译器称之为链接时间代码生成(LTCG)@SebastianRedl:是的,LTO已经启动了。
class SpriteBatch;

template<typename T>
class EntityCollection
{
private:
  SpriteBatch* batch;

public:
  class const_iterator
  {
  private:
    std::vector<Sprite*>::const_iterator inner;

  public:
    const_iterator(const std::vector<Sprite*>::const_iterator& it) : inner(it) { }

    inline bool operator!=(const const_iterator& other) const { return inner != other.inner; }
    inline const const_iterator& operator++() { ++inner; return *this; }
    T* operator*() const;
  };

  const_iterator begin() const;
  const_iterator end() const;

  EntityCollection() : batch(nullptr) { }
  explicit EntityCollection(SpriteBatch* batch) : batch(batch) { }
};
#include "Entities.h"
#include "EntitySprite.h"

template<typename T> 
typename EntityCollection<T>::const_iterator EntityCollection<T>::begin() const { return const_iterator(batch->getChildren().cbegin()); }
template<typename T> 
typename EntityCollection<T>::const_iterator EntityCollection<T>::end() const { return const_iterator(batch->getChildren().cend()); }
template<typename T>
T* EntityCollection<T>::const_iterator::operator*() const { return static_cast<T*>(static_cast<EntitySprite*>(*inner)->getEntity()); }
class EntitySpriteBase
{
private:
  Entity* entity;
public:
  void setEntity(Entity* entity) { ... }
  Entity* getEntity() { ... }
}

class EntitySprite : public EntitySpriteBase, public Sprite { ... }

T* EntityCollection<T>::const_iterator::operator*() const { return static_cast<T*>(reinterpret_cast<EntitySpriteBase*>(*inner)->getEntity()); }