【问题标题】:Namespaces and class members命名空间和类成员
【发布时间】:2024-04-12 04:10:01
【问题描述】:

考虑:

#ifndef __t__ENTITY_H
#define __t__ENTITY_H

#include "../graphics/animation.h"

namespace t {
    namespace entity {
        namespace type {
            enum Enum { GFX = 0, SFX, PFX, AI, MAX };
        }

        //template <class T>
        class Entity {
            public:
                Entity(unsigned int, unsigned int, unsigned int);
                Entity();
                ~Entity();

                int getPosX() { return m_posX; }
                int getPosY() { return m_posY; }
                void setPos(int x, int y) { m_posX = x; m_posY = y; }
                //TODO: const references
                unsigned int getGFXId() { return m_ids[type::GFX]; }
                unsigned int getSFXId() { return m_ids[type::SFX]; }
                unsigned int getPFXId() { return m_ids[type::PFX]; }
                int update(const float);
                int draw();
                int fetchGraphics();
                int fetchSound();
                int fetchPhysics();

            protected:
                //TODO: friend class entity::Handler int reset()
            private:
                int updatePhysics(const float);
                int updateGraphics(const float);
                int updateSound(const float);

                int m_posX, m_posY;
                t::graphics::Animation* m_pAnimation;
                float m_lastTime;
                unsigned int m_ids[type::MAX];
        }; // class Entity
        typedef boost::shared_ptr<t::entity::Entity> SPENTITY;
        typedef boost::shared_ptr<std::vector<SPENTITY> > SPENTITYS;

    } // namespace entity
} // namespace t

#endif // __t__ENTITY_H

在该代码中,成员“t::graphics::Animation* m_pAnimation;”给出“错误:'t::graphics' 尚未声明”,即使“../graphics/animation.h”看起来像:

#ifndef __t__ANIMATION_H
#define __t__ANIMATION_H

#include "frame.h"
namespace t {
    namespace graphics {
        class Animation {
            public:
                Animation();
                Animation(SPFRAMES);

                ~Animation();

                float getLastFrameChange() { return m_lastFrameChange; }
                int getCurrentFrameId() { return m_currentFrameId; }
                //SPFRAME getCurrentFrame() { return m_spFrames.get()[m_currentFrameId]; }//return m_spFrames[m_currentFrameId]; }
                void setCurrentFrame(int val) { m_currentFrameId = val; }

                int update(const float);
                //int fetchDrawables();
            protected:
            private:
                float m_lastFrameChange;
                unsigned int m_currentFrameId;
                unsigned int m_oldFrameId;
                SPFRAMES m_spFrames;
        }; // class Animation
        typedef boost::shared_ptr<Animation> SPANIMATION;
        typedef boost::shared_ptr<std::vector<SPANIMATION> > SPANIMATIONS;
    } // namespace graphics
} // namespace t

#endif // __t__ANIMATION_H

【问题讨论】:

  • 急,代码格式化已经出错了...
  • 我认为修复了格式。
  • 尝试“graphics::Animation* m_pAnimation;”因为您的班级已经在“t”命名空间中
  • @Tom:虽然这里可能不需要限定命名空间,但这样做不会导致编译器错误。
  • 您的包含防护无效。所有包含双下划线或以下划线开头后跟大写字母的名称都保留 供编译器和标准库使用。对于任何以下划线开头的名称也是如此,它没有在类或函数中定义。 (如此简单的规则:避免双下划线并避免前导下划线)。

标签: c++ namespaces header undefined member


【解决方案1】:

除非必要,否则您应该尽量避免让标题包含其他标题。在这种情况下,您可以在第一个标题中放入前向声明。

namespace t {
   namespace graphics {
       class Animation;
   }

   // continue with definitions
}

您的标头可能以错误的顺序包含在某处。也许 Animation 包含需要该枚举的内容,因此包含您的 Entity 标头。

我建议将该枚举移至另一个标题。如果它是类本地的,则将其放在类范围内。

顺便说一句,我也会:

  • 将这些 shared_ptr typedef 移动到另一个仅包含前向声明的标头中。任何想要使用这些 typedef 的人都不一定需要包含类的完整定义,特别是在头文件中使用它们的地方。

  • 使您的代码保持正确。

【讨论】:

  • 在前向声明 boost 和 std 方面存在一些问题(因为它有时认为我的前向声明是重新声明......),但解决方案的其他部分效果很好!
  • boost 声明我通常是前向声明的,例如你可以做 namespace boost { template class shared_ptr; } 在你的 fwd 文件中。对于 STL,我通常只包含 STL 标头,尽管对于 iostream,您通常可以包含 ,例如,您的类支持流式传输。要前向声明 std::string,您必须声明 char_traits 和分配器以及 basic_string,尽管有可能,请参阅 forums.devx.com/showthread.php?t=89483