当前位置:  开发笔记 > 编程语言 > 正文

c ++命名空间头痛

如何解决《c++命名空间头痛》经验,为你挑选了2个好方法。

好的,这个问题已经发展了一些,我想尝试开始(过度)我正在拍摄的基本目标:

在C++资源获取中创建包装旧C语言实体的库代码是初始化,并且还提供基本或更好的异常保证.

使这段代码的客户端能够以非常自然的C++方式使用它,而不会为现有代码创建大量开销,将其转换为使用C++包装器对象(即自动转换为适当的遗留类型,采用传统类型的构造函数等.)

限制库代码的名称空间影响.理想情况下,库有几个子命名空间,提供相关的功能,限制使用命名空间X类型声明的数量和影响 - 就像boost库一样(即使用细节命名空间只注入用户想要的那些符号)使用和隐藏那些作为实现细节的内容;还限制现有符号可能的新含义范围,以避免在用户代码中出现令人惊讶的隐式转换)

要求客户明确要求库中那些他们实际想要注入其代码库的部分.这与限制包含图书馆标题的影响密切相关.客户端代码应该具有合理的控制级别,可以在编译代码时自动使用库的哪些部分进行名称解析.

我自己的库代码不应该充斥着重构 - 脆弱的代码结构.如果库的头文件不必经常声明私有typedef以便访问库的该部分的其余部分,那将是理想的.或者换句话说:我希望我的库能够像我的客户在使用所述库时那样直观地编写.除了已明确"使用"的任何其他名称解析之外,名称解析还应包括定义库的名称空间.

我经常遇到这种情况,我正在寻找更好的方法......

我有一个类,C在命名空间N.C有一个成员,Free.它免费是C管理的东西,并允许C管理新事物.

有几个全局免费功能.在与C相同的名称空间N中也有一些辅助函数,其中一个函数是一个帮助者,它释放由C管理的东西,名为free.

所以我们有类似的东西:

namespace N {

void free(THING * thing);

class C
{
public:
  ... details omitted...
  free()
  { 
    free(m_thing); // <- how best to refer to N::free(THING&)
  }
}

} // namespace N

我可以使用N :: free(m_thing).但这对我来说似乎很不幸.有没有办法引用类范围之外的但没有解析绝对命名空间(范围相对一步)?

在我看来,必须命名N :: free是令人讨厌的,因为如果这是一个独立的功能你就不必这么做.如果班级的方法名称恰好不同(例如处置),你也不需要.但是因为我使用了相同的名字,所以如果你放纵我的比喻,我就无法访问它而不必指定绝对路径的数量 - 而不是相对路径.

我讨厌绝对的道路.它们使名称空间中的移动变得非常脆弱,因此代码重构变得更加丑陋.此外,如何在函数体中命名事物的规则变得更加复杂,使用当前的规则集(正如我所理解的那样) - 不那么规律 - 在人们所期望的和作为程序员的人之间产生分裂.

是否有更好的方法来访问与类相同的命名空间中的独立函数,而不必绝对命名自由函数?

编辑:也许我应该用一个不太抽象的例子:

namespace Toolbox {
  namespace Windows {

// deallocates the given PIDL
void Free(ITEMIDLIST ** ppidl);

class Pidl
{
public:
    // create empty
    Pidl() : m_pidl(NULL) { }

    // create a copy of a given PIDL
    explicit Pidl(const ITEMIDLIST * pidl);

    // create a PIDL from an IShellFolder
    explicit Pidl(IShellFolder * folder);

    ...

    // dispose of the underlying ITEMIDLIST* so we can be free to manage another...
    void Free();
};

所以ITEMIDLIST*来自各个地方,并使用CoTaskMemFree()销毁.我可以将Pidl作为全局名称引入 - 以及作为我的工具箱库一部分的"Windows Shell.h"头中的所有辅助函数.

理想情况下,我会根据它们的相关内容对我的库中的一些工具进行分段 - 在这种情况下,上述所有工具都与Windows中的COM编程有关.我已选择Toolbox作为我的库的基本命名空间,并且目前认为我将使用Toolbox :: Windows用于非常windows-y的函数,类等.

但是C++命名空间和名称解析规则似乎使这非常困难(因此这个问题).创建代码的这种分段是非常不自然的 - 因为koenig查找失败(因为ITEMIDLIST不在我的Toolbox :: Windows命名空间中),而且我没有能力将其移动到那里!我也不应该这样.语言应该足够灵活,IMO,允许扩展库(如我的Toolbox库)扩展其他人的代码而不必将我的扩展注入其命名空间(在Win32和一般广大的情况下)今天存在的大多数代码都是GLOBAL NS--这首先是制作命名空间的全部要点:避免全局NS拥挤/污染/模糊/编程意外).

所以,我回过头来看,有没有更好的方法:扩展现有的代码库,同时不用我的扩展来污染他们的NS,但仍然允许直观和有用的名称解析,如果我的代码在他们的NS中但是我的代码客户端明确地介绍了(即我不想肆无忌惮地注入我的代码,但只是在明确请求时)?

另一个想法:如果我有以下内容,也许满足我上面的criterea会是什么:

using namespace X {
  code here...
}

我可以在任何地方放置这样的构造,包括在标题中,我不必担心将X拖入我的客户端的代码中,但是如果我在的话,我将有同样的自由来编写我的源代码.根命名空间.



1> Pavel Minaev..:

我没有看到避免在free()这里限定命名空间范围,但应该注意这与"绝对路径"不同.首先,如果你有嵌套的命名空间,你只需要引用最里面的命名空间:

namespace N1 {
  namespace N2 {
    namespace N3 {
      void free(THING * thing);

      class C {
      public:
        free() {
          N3::free(m_Thing); // no need to do N1::N2::
        }
      };
    }
  }
}

[编辑]回应编辑过的问题.同样,我没有看到任何方法在您描述的确切场景中执行此操作.然而,它似乎不是惯用的C++方法 - 更常见的方法是提供自己的包装类来ITEMIDLIST管理所有分配,RAII风格,并暴露原始句柄(例如通过转换运算符a la ATL,或明确的成员函数,c_str()如果你想要额外的安全性).这将free完全取消您的需要,并且对于您可能想要的任何其他免费功能,因为您控制包装器类型和它所在的命名空间,您可以像往常一样使用ADL.

[编辑#2].这部分问题:

允许直观和有用的名称解析,如果我的代码在他们的NS中但由我的代码的客户端明确地引入(即我不想无缘无故地注入我的代码,但仅在明确请求时)?

这不正是你把它放在命名空间中,而你的客户端写作using namespace ...会实现吗?



2> Kirill V. Ly..:

您有两种选择:

    完全限定功能名称.

    让Koenig查找完成工作(如果THING属于命名空间N).

我会选择第一个具有如此流行的功能名称的人free.

替代选项是使用m_thing->Release()或类似的东西.

推荐阅读
勤奋的瞌睡猪_715
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有