27

我发现我的 C++头文件对于所有完全限定的类型(其深度为 4 个嵌套命名空间)都很难阅读(而且输入起来非常乏味)。这就是问题(所有答案都给出了实现它的混乱替代方案,但这不是问题):是否有充分的理由反对在 C++ 语言的结构和类中引入作用域 using 指令(虽然允许使用作用域)函数中的声明)?

例如

class Foo : public Bar
{
    using namespace System;
    using namespace System::Network;
    using namespace System::Network::Win32::Sockets;
    using Bar::MemberFunc; // no conflict with this

    // e.g. of how messy my header files are without scoped using-directive
    void FooBar(System::Network::Win32::Sockets::Handle handle, System::Network::Win32::Sockets::Error& error /*, more fully-qualified param declarations... */);
};

因为namespaceis 是一个关键字,所以我认为它的独特性足以与范围内的 using 声明(例如Bar::MemberFunc.

编辑:仔细阅读问题--->我已经加粗了。提醒:我们不是在这里讨论如何提高示例的可读性。建议如何在 C++ 语言中实现作用域使用指令(即通过添加关键字/构造等)不是一个答案(如果你能找到一种使用现有 C++ 语言标准来实现它的优雅方法,那么它会当然是答案)!

4

5 回答 5

13

有时我这样做是为了达到几乎相同的效果:

namespace detail {
    using namespace System;
    using namespace System::Network;
    using namespace System::Network::Win32::Sockets;

    class Foo : public Bar
    {
         void FooBar(Handle handle, Error& error);
    };
}
using detail::Foo;
于 2010-12-06T05:17:19.347 回答
11

鉴于using没有继承类范围内的声明,这可能会起作用。该名称仅在该类声明内或嵌套类的声明内有效。但我认为这有点用一个应该更大的想法来重载一个类的概念。

在 Java 和 Python 中,单个文件以特殊方式处理。您可以拥有import将来自其他命名空间的名称注入文件的声明。这些名称(嗯,不完全是 Python,但这里解释起来太复杂了)只在该文件中可见。

对我来说,这种能力不依赖于类声明,而是赋予它自己的范围。如果有意义的话,这将允许在多个类声明中使用注入的名称,甚至在函数定义中使用。

这是我更喜欢的一个想法,因为它允许这些事情,同时仍然为您提供使用声明的类级别的好处:

using {
   // A 'using' block is a sort of way to fence names in.  The only names
   // that escape the confines of a using block are names that are not
   // aliases for other things, not even for things that don't have names
   // of their own.  These are things like the declarations for new
   // classes, enums, structs, global functions or global variables.
   // New, non-alias names will be treated as if they were declared in
   // the scope in which the 'using' block appeared.

   using namespace ::std;
   using ::mynamespace::mytype_t;
   namespace mn = ::mynamespace;
   using ::mynamespace::myfunc;

   class AClass {
     public:
      AClass(const string &st, mytype_t me) : st_(st), me_(me) {
         myfunc(&me_);
      }

     private:
      const string st_;
      mn::mytype_t me_;
   };
// The effects of all typedefs, using declarations, and namespace
// aliases that were introduced at the level of this block go away
// here.  typedefs and using declarations inside of nested classes
// or namespace declarations do not go away.
} // end using.

// Legal because AClass is treated as having been declared in this
// scope.
AClass a("Fred", ::mynamespace::mytype_t(5));

// Not legal, alias mn no longer exists.
AClass b("Fred", mn::mytype_t);

// Not legal, the unqualified name myfunc no longer exists.
AClass c("Fred", myfunc(::mynamespace::mytype_t(5));

这类似于为函数中的局部变量声明一个块。但是在这种情况下,您声明了一个非常有限的范围,您将在其中更改名称查找规则。

于 2010-12-06T05:24:42.610 回答
0

也许命名空间别名?

namespace MyScope = System::Network::Win32::Sockets;
于 2010-12-06T03:12:41.027 回答
0

您可以在类声明中使用 typedef 来实现相同的目的

class Foo : public Bar
{
      typedef System::Network::Win32::Sockets::Handle Handle;
      typedef System::Network::Win32::Sockets::Error Error;

      void FooBar(Handle handle, Error& error);
};
于 2014-03-04T09:09:58.447 回答
-2

命名空间的明显好处是它们允许您避免命名冲突。然而,通过在类声明中引入整个命名空间,这种好处就失效了。System 命名空间中的函数完全有可能与您自己的 Bar::MemberFunc 函数发生冲突。当您添加注释“与此不冲突”时,您甚至会在示例代码中注意到这一点。

您显然不想像这样将整个命名空间引入您的类中:

using namespace System;
using namespace System::Network;
using namespace System::Network::Win32::Sockets;

而且你不能在类声明中添加更窄范围的 using 语句。将这些直接放入类声明中是非法的。

using System::Network::Win32::Sockets::Handle;
using System::Network::Win32::Sockets::Error;

可以做的是使用未命名的命名空间。所以,你的头文件看起来像这样:

namespace {
    using System::Network::Win32::Sockets::Handle;
    using System::Network::Win32::Sockets::Error;
}

class Foo : public Bar
{
    using Bar::MemberFunc;

    // clean!
    void FooBar(Handle handle, Error& error /*, more declarations*/);
};

这具有三个明显的优点。

  1. 不介绍整个命名空间的内容。这有助于更轻松地避免命名冲突。
  2. 在你的类声明之前,你有一个你的类依赖什么才能正常工作的列表。
  3. 您的函数声明很干净。

如果我错了,请纠正我;我只是简单地测试了这一点。很快写了一个例子,它编译了。

于 2010-12-06T05:36:22.000 回答