我怎样才能避免这种丑陋的嵌套类c ++代码

时间:2015-01-27 17:27:17

标签: c++ class oop nested shared-ptr

我用SDL用C ++编写游戏。我用C语言写了一年多的游戏,现在我在过去的7个月里一直用C ++写作。我试图避免几乎所有的全局变量并转移到所有权系统,其中每个对象都由其他东西拥有。这样我就可以管理拥有shared_ptr成员的类的生活,几乎从不担心释放指针。

例如,我的游戏是一个带有子系统的类。

class Game
{
public:
   Game();
   ~Game();
   void runFrame();

   std::shared_ptr<Display> display;
   std::shared_ptr<Audio> audio;
   std::shared_ptr<Save> save;
};

但是我遇到了乱看的嵌套类,比如下面的音频类。

class Audio
{
public:
   Audio(Game& parent);
   ~Audio();

   struct MusicFiles;
   struct SfxFiles;
   std::shared_ptr<MusicFiles> musicFiles;
   std::shared_ptr<SfxFiles> sfxFiles;

private:
   class Music
   {
   public:
      class File
      {
      public:
         File(Music& parent, std::string fileAddr);
         ~File();
         void play();
         void fadeIn();
         void stop();
      private:
         Music& _parent;
         std::string addr;
         Mix_Music* chunk;
      };

      Music(Audio& parent);
      ~Music();
      void setVolume();

   private:
      Audio& _parent;
      bool _enabled;
      int _volume;
   };

   class Sfx
   {
   public:
      class File
      {
      public:
         File(Sfx& parent, std::string fileAddr);
         ~File();
         void play();
         void stop();
      private:
         Sfx& _parent;
         std::string addr;
         Mix_Chunk* chunk;
         int channel;
      };

      Sfx(Audio& parent);
      ~Sfx();
      void setVolume();

   private:
      Audio& _parent;
      bool _enabled;
      int _volume;
   };

   Game& _parent;
   Music _music;
   Sfx _sfx;
};

我有嵌套类,因为我不喜欢在每个函数名中写“Music”或“Sfx”,如setMusicVolume(),setSfxVolume(),setMusicHook(),setSfxHook()等。 我可以拉出嵌套类,但Music和Sfx只需要存在于Audio类中。我宁愿重组一切,也有更好的设计。

你有更好的设计建议吗?

2 个答案:

答案 0 :(得分:3)

将您的各种课程组织成namespace以对其进行分组,而不是将其分组。一旦它成长,这个东西将变得非常难以维持。您希望使用您的类来封装功能,并为“外部世界”提供简单而全面的界面。通常,每个类都将获得自己的头文件(.h.hpp)和编译单元(.cpp)。

接受使用getter和setter函数many good reasons - 它们是良好封装的基础。如果您真的需要,可以始终在嵌套类中使用friend class Audio,使privateprotected成员对Audio可见,但不能对项目中的所有其他类可见可能(在未来的某个时间,可能)包括这些类。

你说你不喜欢写audio.setMusicVolume(0.8f)而不是audio.music.setMusicVolume(0.8f)。有人可能会说audio.getMusic().setVolume(0.8f)是一个很好的妥协,但Demeter不同意。通过使用诸如setMusicVolume之类的包装函数,每个其他类只需要了解Audio并与Music进行通信,而Audio是严格内部的,并且只有Music本身知道。如果你使用函数链,你会失去这个优势,并向世界展示SfxAudio - 这不一定是坏事。如果你想坚持你的语法,我的建议是保持公共接口非常小and use friend,以便在需要时向{{1}}公开更多功能。

答案 1 :(得分:1)

仅供参考,除了使用命名空间之外,嵌套类型可以通过使用其限定名称放置在行外,就像成员函数一样。所以你可以这样做:

class Audio
{
public:
   Audio(Game& parent);
   ~Audio();

   struct MusicFiles;
   struct SfxFiles;
   std::shared_ptr<MusicFiles> musicFiles;
   std::shared_ptr<SfxFiles> sfxFiles;

private:
   class Music;
};

在另一个档案中

#include "Audio.h"

class Audio::Music
{
public:
  class File;

  Music(Audio& parent);
  ~Music();
  void setVolume();

private:
  Audio& _parent;
  bool _enabled;
  int _volume;
};