【问题标题】:Defining template class member functions in a namespace?在命名空间中定义模板类成员函数?
【发布时间】:2017-06-30 02:25:16
【问题描述】:

我环顾四周,试图找到答案。是否可以在 cpp 文件的命名空间中定义模板类的成员函数?尝试执行此操作时出现错误。

这是我要编译的两个文件。

ArrayList.hpp

     template<typename T>
     class ArrayList{
          ArrayList();
          ~ArrayList();
     }

ArrayList.cpp

    #include "ArrayList.hpp"

    namespace{

        template<typename T>
        ArrayList<T>::ArrayList(){

         /* function body goes here */

        }

        ArrayList<T>::~ArrayList(){

         /* function body goes here */

        }

编译器错误

 error: cannot define or
  redeclare 'ArrayList<T>' here because namespace '' does not enclose
  namespace 'ArrayList'
  ArrayList<T>::ArrayList()

【问题讨论】:

  • 命名空间应该被命名,即:namespace myarray {
  • @Serge 你也可以在 C++ 中使用匿名命名空间
  • @Serge 导致类似的错误 -> 'cannot define or redeclare 'ArrayList' here because namespace 'myarray' does not enclose namespace 'ArrayList' ArrayList::ArrayList() '
  • @user87002 请将您的新代码作为编辑发布在您的问题中,包括头文件和实现文件中的命名空间定义
  • 检查你的代码是否有不平衡的大括号。您错过了命名空间示例中的最后一个。

标签: c++


【解决方案1】:

您需要在定义其成员函数的同一命名空间中声明您的类。

你在析构函数之前缺少template&lt;typename T&gt;

namespace ANamespace
{

    template<typename T>
    class ArrayList
    {
        ArrayList();
        ~ArrayList();
    };

    template<typename T>
    ArrayList<T>::ArrayList()
    {

        /* function body goes here */

    }

    template<typename T>
    ArrayList<T>::~ArrayList()
    {

        /* function body goes here */

    }
}

【讨论】:

    【解决方案2】:

    是否可以在 cpp 文件的命名空间中定义模板类的成员函数?

    不,这是不可能的。与任何其他类声明一样,成员函数声明及其定义必须出现在同一命名空间中。

    您的示例中使用的未命名命名空间也只能在该特定翻译单元中看到。

    您通常不能将模板定义放在单独的翻译单元中(除非您有特殊的特殊情况)。请在此处阅读更多信息:

    Why can templates only be implemented in the header file?


    如何解决?

    只需将所有内容移到头文件中,然后像这样删除未命名的命名空间:

    ArrayList.hpp

     template<typename T>
     class ArrayList{
          ArrayList();
          ~ArrayList();
     }; // Semicolon at end of class declaration is essential
    
     template<typename T>
     ArrayList<T>::ArrayList(){
         /* function body goes here */
     }
    
     template<typename T> // <<<<< Repeat for evey function definition
     ArrayList<T>::~ArrayList(){
        /* function body goes here */
     }
    

    如果你真的想拥有一个命名空间,只需提供一个命名空间并将上面的所有内容都包含在其中(仍在标题中):

     namespace MyUtilities {
         template<typename T>
         class ArrayList{
         public: // <<<<<< Allow access to these functions
              ArrayList();
              ~ArrayList();
         };
    
         template<typename T>
         ArrayList<T>::ArrayList(){
              /* function body goes here */
         }
    
         template<typename T>
         ArrayList<T>::~ArrayList(){
             /* function body goes here */
         }
     }
    

    请查看完整的工作示例here

    还要使这些东西可用,如上所示,使用 public 关键字。

    【讨论】:

      【解决方案3】:

      首先,您不能在.cpp 文件中定义模板类的方法。您需要在头文件本身中定义模板类方法(或在另一个文件中,然后通过预处理器将其导入头文件本身)更多请参阅Why can templates only be implemented in the header file?

      匿名命名空间namespace { 用于定义具有内部链接的事物,即类似于static 对实现文件中定义的函数的影响。阅读本文以获取更多信息Why are unnamed namespaces used and what are their benefits?

      但是在您的情况下,您希望将类方法定义为外部可见,因为您已在头文件中公开声明了它们。因此,您可能不希望这些定义位于匿名命名空间中。

      如果你有一个命名空间将你的类包含在你的头文件中,例如namespace array_list,那么你应该在同一个命名空间中定义你的类方法在头文件本身,因为它是一个模板类并且需要在任何使用的地方可见。

      【讨论】:

        最近更新 更多