【问题标题】:Separate class for a namespace advisable?建议命名空间的单独类?
【发布时间】:2013-07-07 13:04:27
【问题描述】:

我有几个函数想在许多不同的类中使用。我有几个类是从一个基类派生的,所以试图让它基类保存函数,然后子类可以调用它们。这似乎会导致链接错误,因此根据这个问题 (Advantages of classes with only static methods in C++) 的建议,我决定给命名空间一个摇摆,但每个头文件/文件包含的唯一文件是 resource.h,我不想要为我的函数放置一个命名空间,因为它似乎专门用来搞乱。

我的问题是,如何创建一个只包含命名空间或我想使用的函数的类,以便我可以只包含这个类并根据需要使用函数?

提前感谢您的帮助,我在互联网上找到的答案只关注一个文件,而不是我希望解决的多个文件:)

【问题讨论】:

  • 对不起,为什么你不能使用命名空间?如果您只能使用具有静态方法的类,则可以使用命名空间。
  • 我的理解是命名空间只能被以某种方式连接的类“看到”。如果我错了,请纠正我,但如果是这种情况,那么我的主类将无法在我的播放器类中看到命名空间,例如:)
  • 这种理解听起来是错误的。例如,我可以创建自己的容器类,并将其与 std 命名空间中的标准库算法一起使用。
  • 所以,到目前为止,我有 Main、Entity 和 Player,Player 有 Entity 作为基础,而 Main 中只会有 Player 的对象。我可以在实体中创建一个命名空间(我计划制作更多实体)并在 Main 中使用它吗? :) 顺便说一句,谢谢你的帮助!
  • 你不能在类中创建命名空间。您可以将类、函数和对象放在命名空间内。

标签: c++ namespaces


【解决方案1】:

您似乎对如何使用命名空间感到困惑。使用命名空间时要记住以下几点:

  • 您使用语法namespace identifier { /* stuff */ } 创建命名空间。 {} 之间的所有内容都将在此命名空间中。
  • 您不能在用户定义的类型或函数中创建命名空间。
  • 命名空间是一个开放组结构。这意味着您可以稍后在其他代码中添加更多内容到这个命名空间中。
  • 命名空间的声明方式与其他一些语言结构不同。
  • 如果您希望某些类和/或函数位于命名空间范围内,请将其与命名空间语法一起包含在定义它的标题中。当标头获得#include'd 时,使用这些类的模块将看到命名空间。

例如,在您的Entity.h 中,您可能会这样做:

// Entity.h
#pragma once

namespace EntityModule{
class Entity
{
public:
  Entity();
  ~Entity();
  // more Entity stuff
};

struct EntityFactory
{
  static Entity* Create(int entity_id);
};

}

在您的main.cpp 中,您可以这样访问它:

#include "Entity.h"

int main()
{
  EntityModule::Entity *e = EntityModule::EntityFactory::Create(42);
}

如果您还希望 Player 位于此命名空间内,那么也只需将其与 namespace EntityModule 包围:

// Player.h
#pragma once
#include "Entity.h"

namespace EntityModule{
class Player : public Entity
{
  // stuff stuff stuff
};
}

由于上面的第 3 点,这有效。

如果出于某种原因您觉得需要在类中创建命名空间,您可以使用嵌套类在一定程度上进行模拟:

class Entity
{
public:
  struct InnerEntity
  {
    static void inner_stuff();
    static int  more_inner_stuff;
    private:
      InnerEntity();
      InnerEntity(const InnerEntity &);
  };
  // stuff stuff stuff
};

虽然这样做有一些重要的区别和注意事项:

  • 所有内容都用static 限定,表示没有关联的特定实例。
  • 可以作为模板参数传递。
  • 最后需要;
  • 您无法使用abusing namespace Entity::InnerEntity; 创建方便的速记。但也许这是件好事。
  • 与命名空间不同,classstruct封闭 结构。这意味着一旦定义,您就无法扩展它包含的成员。这样做会导致多重定义错误。

【讨论】:

  • 叹息,这实际上是我在你发布之后发布的。我会保留我的参考和另一个例子,但是,OP 请记住@greatwolf 是第一个。
  • 非常有帮助,谢谢 :) 我稍后会尝试实现它。你们俩都帮了大忙,谢谢:)
【解决方案2】:

你可以将任何东西放在命名空间中,但你不能将命名空间放在事物内部(这不是一种非常正式的说法,但我希望你明白我的意思。

有效

namespace foospace
{
    class foo
    {
    public : 
        foo();

        ~foo();

        void eatFoo();

    };
}

无效

namespace foospace
{
    class foo
    {
    public : 
        foo();

        ~foo();

        namespace eatspace
        {  
            void eatFoo();
        }

    };
}

我不能 100% 确定第二个示例不会编译,但无论如何,你不应该这样做。

现在,从你的 cmets 看来你想要这样的东西:

在文件Entity.h中,你的实体类定义:

namespace EntitySpace
{
    class Entity
    {
    public : 
        Entity();
        ~Entity();   
    };
}

在文件Player.h

#include "Entity.h"
namespace EntitySpace
{
    class Player : public Entity
    {
    public : 
        Player();
        ~Player();   
    };
}

在 main.cpp 文件中

#include "Player.h"

int main()
{
    EntitySpace::Player p1;
    EntitySpace::Player p2;

}

因此,您在 EntitySpace 命名空间中调用 Player。希望这能回答您的问题。

【讨论】:

  • 两个都是很好的答案,谢谢,我给了greatwolf这个答案,因为他的回答稍微涵盖了我认为我的问题,不过你的回答非常有助于了解更多关于命名空间的信息,再次感谢你:)
猜你喜欢
  • 2011-08-27
  • 1970-01-01
  • 2013-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-23
  • 2017-05-27
相关资源
最近更新 更多