首页 文章

C命名空间函数

提问于
浏览
24

我是一名Java开发人员,我对C很新 . 我需要实现某种实用类,我正在考虑将这些方法实现为static . 但是,我遇到了关于命名空间函数与静态方法的this stackoverflow question,并且显然名称空间函数是首选方法 . 所以我想知道如果有关于如何实现命名空间功能的任何文章或示例 . 例如,我应该如何在头文件中声明命名空间函数?头文件是否只包含类头文件等函数定义,实现应该在cpp文件中,还是我应该直接在头文件中实现函数?

基本上,我试图实现一个应用程序来解析包含一些命令的文本文件 . 所以我正在考虑实现静态辅助方法来处理文本处理 . 例如readCommand(字符串行) . 如果我的方向错误,请告诉我 . 谢谢

3 回答

  • 15

    我应该如何在头文件中声明命名空间函数?

    namespace MON {
    // extern:
    t_ret func(const t_param& pValue);
    // 'inline':
    inline t_ret inline_func(const t_param& pValue) { ... }
    } // << MON
    

    头应该只包含类头文件等函数定义,实现应该在cpp文件中,还是我应该直接在头文件中实现函数?

    这取决于您是否希望它们(可能)内联或导出 . 这通常归结为最小化依赖性 .

    扩展出口或内联:

    你经常喜欢extern函数来减少c中的依赖关系 . 这相当于在类方法中将定义与声明分开:

    file.hpp

    namespace MON {
    // extern:
    t_ret func(const t_param& pValue);
    } // << MON
    

    file.cpp

    #include "hefty_stuff.hpp"
    
    MON::t_ret MON::func(const t_param& pValue) { ... }
    

    但是,有时候定义在某些情况下是可见的,通常是为了提高性能,或者当你知道大小很重要并且 Headers 不包括在很多地方时 . 因此, inline 变体也是一种选择 .

    内联函数仍然可以被导出,并且它可以按要求内联 - 但是,任何内联函数副本都可以合并(具体来说,实现可以自由地假设所有定义都相同,并且函数的任何副本都是不必要的) .

    使用导出的定义,您可以选择性地限制(或隔离)您的包含依赖项 . 也就是说, #include "hefty_stuff.hpp" 不需要在 Headers 中使用 file.hpp 中的函数 .


    基本上,我正在尝试实现一个应用程序来解析包含一些命令的文本文件 . 所以我正在考虑实现静态辅助方法来处理文本处理 .

    好吧,这里应该避免 static . c使用单定义规则 . static 只会导致大量不必要的副本 . 此外,匿名命名空间是c的 static 函数的c方法:

    namespace {
    t_ret func(const t_param& pValue) { ... }
    } // << anon
    

    注意:匿名命名空间也可能导致不必要的副本 . 你将它们用作静态函数的替代的原因是你想要或者需要偏离one-definition-rule,并且不想在可能被“解析”的范围中声明符号 .


    最后一点是关于 template<> 的声明 . 使用模板时,除非编译器支持extern模板,否则定义必须在使用的位置可见 . 对于模板,您可以通过多种方式完成定义可见性 . 通常,人们只需简单地声明定义,或为定义添加 Headers ,该 Headers 包含在 Headers 的末尾或根据需要 . 使用模板,不需要声明函数 inline 以避免多个定义错误 .

  • 1

    我应该如何在头文件中声明命名空间函数?

    namespace YourNamespace
    {
        void fun1();
        void fun2();
    }
    

    头文件是否只包含类头文件等函数定义,实现应该在cpp文件中,还是我应该直接在头文件中实现函数?

    如果命名空间中的函数是静态的,则可以在头文件中实现函数,或者必须在cpp文件中实现 .

  • 22

    您可以在标头中声明函数:

    namespace A {
        void foo();
    }
    

    并在.cpp中实现:

    namespace A {
      void foo() { std::cout << "foo!"; }
    }
    

    您也可以将实现放在 Headers 中,确保将其声明为 inline 以避免破坏one definition rule

    namespace A {
        inline void foo() { std::cout << "foo()!"; }
    }
    

    请注意,将实现放在标头中意味着客户端代码对实现具有编译依赖性,以及用于实现的标头 . 在上面的示例中,客户端代码现在依赖于标头,如果我们做一些微不足道的事情,比如在打印输出中添加感叹号,我们需要重新编译,而不是重新链接所有客户端代码 .

    将模板函数的实现放在头部或头部包含的文件中是非常重要的,这些不能放在.cpp中:

    namespace B {
      template <class T>
      inline void foo(const T& t) { std::cout << t.name() << "\n"; }
    }
    

相关问题