代码之家  ›  专栏  ›  技术社区  ›  Adam Naylor

C++命名空间的建议

  •  71
  • Adam Naylor  · 技术社区  · 17 年前

    我只是在教C++ C++命名空间(来自C语言背景),我真的开始认为,即使C++的所有东西都比大多数其他语言好,嵌套的名字空间也不是其中之一!

    我认为为了声明一些嵌套名称空间,我必须执行以下操作,对吗

    namespace tier1
    {
        namespace tier2
        {
            namespace tier3
            {
                /* then start your normal code nesting */
            }
        }
    }
    

    与之相反:

    namespace tier1::tier2::tier3
    {
    }
    

    当我需要向前声明时,这变得更加疯狂:

    namespace tier1
    {
        namespace tier2
        {
            namespace forward_declared_namespace
            {
                myType myVar; // forward declare
            }
            namespace tier3
            {
                /* then start your normal code nesting */
                class myClass
                {
                    forward_declared_namespace::myType myMember;
                }
            }
        }
    }
    

    请记住,我开发的典型系统包括:

    MyCompany::MySolution::MyProject::System::[PossibleSections]::Type
    

    这就是为什么你在C++实例中不太经常使用命名空间的原因吗?或者通常只使用单个(非嵌套)名称空间?

    使现代化

    对任何感兴趣的人来说, this is how I ended up

    9 回复  |  直到 13 年前
        1
  •  114
  •   anon anon    17 年前

    C++中正确使用命名空间的一个很好的例子是C++标准库。这个相当大的库中的所有内容都放在一个名为 -没有尝试或需要将库分解为(例如)I/O子命名空间、数学子命名空间、容器子命名空间等。

    C++中建模的基本工具是类(在某种程度上是模板),而不是命名空间。如果您觉得需要嵌套,则应该考虑使用嵌套类,它具有优于名称空间的以下优点:

    • 他们可以控制访问
    • 它们无法重新打开

        2
  •  24
  •   Binary Worrier    9 年前

    C++命名空间比以前的版本有很大的改进(即根本没有命名空间)。C#名称空间扩展了这个概念并与之一起运行。我建议您将名称空间保持在一个简单的平面结构中。

    编辑 由于我在这里概述的缺点,你建议这样做吗?

    C++命名空间的目的是阻止C开发人员遇到的现实世界问题,在使用两个第三方LIBs导出相同函数名时,它们会遇到名称冲突。C开发人员对此有各种解决办法,但这可能是一个严重的难题。

    想法是STL etc具有 std:: 命名空间中,由“XYZ公司”提供的LIB将具有 xyz:: 名称空间,你在“ABC公司”工作 全部的 你的东西在一个 abc:: 命名空间。

        3
  •  20
  •   mip    6 年前

    当前瞻性声明如下所示时,我会做什么:

     namespace abc { namespace sub { namespace subsub { class MyClass; }}}
    

    我的正向声明被折叠成一行。转发声明的可读性被牺牲,以换取其余代码的可读性。对于定义,我也不使用缩进:

     namespace abc {
     namespace sub {
     namespace subsub {
     
     class MyClass 
     {
        public:
           MyClass();
    
           void normalIntendationsHere() const;
     };
    
     }
     }
     }
    


    由于C++17,您可以使用问题作者提出的语法来声明名称空间。

    namespace A::B::C { ... }
    

    namespace A::B::C { ... } 到 namespace A { namespace B { namespace C { ... } } }

    https://en.cppreference.com/w/cpp/language/namespace

        4
  •  8
  •   Bill Lynch    17 年前

    namespace foo = A::B::C::D;
    

    然后将A::B::C::D引用为foo。但只有在某些情况下。

        5
  •  6
  •   yairchu    8 年前

    namespace myLib { namespace details {
    
    /* source code */
    
    } } /* myLib::details */
    

    C++源代码最终编译成二进制,不像C/j/java中的二进制。因此,名称空间只是为变量命名冲突提供了一个很好的解决方案。它不适用于类层次结构。

    我经常在代码中保留一到两个名称空间级别。

        6
  •  4
  •   Mykola Golubyev    17 年前

    首先,可以避免名称空间缩进,因为没有理由这样做。

    只是不要在一个.h文件中混合使用不同的命名空间层次结构。名称空间是函数接口声明的一种额外注释。查看名称空间和类名应该可以解释很多东西。

    namespace product
    {
    namespace DAO
    {
    
    class Entity
    {
    };
    
        7
  •  0
  •   Ace_Of_John    12 年前

    我发现你可以像这样模仿c#名称空间;

    namespace ABC_Maths{
        class POINT2{};
        class Complex{};
    }
    
    namespace ABC_Maths_Conversion{
        ABC_MATHS::Complex ComplexFromPOINT2(ABC_MATHS::POINT2)
        {return new ABC_MATHS::Complex();}
    
        ABC_MATHS::POINT4 POINT2FromComplex(ABC_MATHS::COMPLEX)
        {return new ABC_MATHS::POINT2();}
    }
    
    namespace ABC
    {
    }
    

    但代码似乎不是很整洁。我希望有冗长的用法

    namespace ABC{
        class Maths{
            public:
            class POINT2{};
            class Complex:POINT2{};
            class Conversion{
                public:
                static Maths.Complex ComplexFromPOINT2(MATHS.POINT2 p)
                {return new MATHS.Complex();}
    
                static MATHS.POINT2 POINT2FromComplex(MATHS.COMPLEX p)
                {return new ABC::MATHS.POINT2();}// Can reference via the namespace if needed
    } /*end ABC namespace*/
    

    这仍然有点冗长。但确实感觉有点糟糕。

    并听到它似乎是最好的做法

    namespace ABC
    {
        class POINT2{};
        class Complex:POINT2{};
        Complex ComplexFromPOINT2(POINT2 p){return new Complex();}
        POINT2 POINT2FromComplex(Complex){return new POINT2();}
    }
    

    听说用法会是什么样子

    int main()
    {
        ABC_Maths::Complex p = ABC_Maths_Conversion::ComplexFromPOINT2(new ABC_MATHS::POINT2());
    
        // or THE CLASS WAY
    
        ABC.Maths.Complex p = ABC.Maths.Conversion.ComplexFromPOINT2(new ABC.Maths.POINT2());
    
        // or if in/using the ABC namespace
    
        Maths.Complex p = Maths.Conversion.ComplexFromPOINT2(new Maths.POINT2());
    
        // and in the final case
    
        ABC::Complex p = ABC::ComplexFromPOINT2(new ABC::POINT2());
    }
    

    C++中命名空间的最佳用法是停止说我的超级CUT函数(每次调用它的TEN),使之与STD::CUT函数混合(这远不如印象深刻)。

    仅仅因为C和C++有名字空间,并不意味着命名空间是相同的。它们既不同又相似。C++的命名空间的思想必须来自C++命名空间。一定有人已经看到了相似但不同的东西可以做什么,并且没有足够的想象力来给它起自己的原始名称,比如“ClassPath”,这将更有意义,因为它是类的路径,而不是提供每个空间都可以有相同名称的命名空间

    我希望这对某人有帮助

    我忘了说所有这些方法都是有效的,前两种方法的适度使用可以结合到第三种方法中,以创建一个有意义的库ie(不是很好的例子)

    _INT::POINT2{}
    

    和

    _DOUBLE::POINT2{}
    

    因此,您可以使用更改精度级别

    #define PREC _DOUBLE 
    // or #define PREC _INT 
    

    然后为双精度POINT2创建PREC::POINT2的实例

    对于c#或java名称空间来说,这不是一件容易的事情

    显然,这只是一个例子。想想这个用法是怎么读的。

        8
  •  -1
  •   Jimmy J    17 年前

        9
  •  -1
  •   icecream    14 年前

    namespace.h

    #define NAMESPACE_TIER1_TIER2_TIER3 \
        namespace tier1 { \
        namespace tier2 { \
        namespace tier3 {
    
    #define END_NAMESPACE_TIER1_TIER2_TIER3 }}}
    

    要在其他地方使用它:

    另一个文件

    #include "./namespace.h"
    
    NAMESPACE_TIER1_TIER2_TIER3;
    
    /* Code here */
    
    END_NAMESPACE_TIER1_TIER2_TIER3;
    

    推荐文章