c ++程序有未定义的引用'使用g ++但我已经在编译

时间:2017-12-07 21:50:41

标签: c++ templates linker g++

TL; DR

在尝试运行在非模板化类中具有模板化函数的程序时,我收到了undefiend reference错误消息。在这个帖子的评论中提出了多个解决方案,我选择的那个解决方案在本文末尾进行了说明。

参见"问题陈述"下面是我的代码输出的错误。

编辑1:2017年12月8日

  • 更改了我的代码示例,只需对自己的ide进行简单的复制/面食即可轻松复制问题。
  • 此帖子的KevinDevSolar评论中提供了此问题的解决方案 - 非常感谢大家!事实证明,我需要做以下其中一项:
    • 将我的模板函数的定义从.cpp文件移动到.h文件。
    • 明确提供可能通过模板类类型传递的可能数据类型的定义......这听起来像是很多工作。 我现在忙着为决赛做准备,但是当我得到片刻时,我会回来并发布更改的代码来演示修复。

编辑2:2017年12月19日

  • 看到这篇文章标题中的问题源于在我的非模板课程中不恰当地定义我的模板化函数,我决定在帖子前面添加TL; DR以方便读者使用。
  • 在发布的底部添加了我选择的解决方案策略。
    • 这应该清楚地展示了在非模板类中使用模板化函数的一种方法。

问题陈述

使用g++编译和链接我的类文件,这给了我{driver}调用undefined reference的{​​{1}}投诉。显然它无法在mergesortImproved.cpp中找到我的函数的定义。

mergesortImproved::beginSorting(std::vector<int> &data)

旁注,msI是我缩写mergesortImproved的方式。这是教师所需的文件名,但看到它有点麻烦,我已经把它称为msI。

我这样说,以防msI弹出某个地方,我忘了在这篇文章中将名称更改为mergesortImproved。

此情况的具体细节

所有文件都在同一个文件夹中,我确保在尝试编译和链接时包含所有文件。

我还尝试在Windows 10计算机和Linux计算机上进行编译。

我已经阅读了许多其他类似的问题,似乎这个问题的10倍中有9个来自程序员没有编译程序的所有文件,如应该。所以......

编辑:几乎忘了包含我试图使用的Windows和Linux机器的g ++版本。

对于Windows 10计算机:

$ g++ -o msI_out -std=c++17 *.cpp
/tmp/ccZ0tzev.o: In function `generateTimeData(quicksort&, mergesort&, mergesortImproved&, int const&, long double&, std::vector<int, std::allocator<int> >&)': 
driver.cpp:(.text+0xaac): undefined reference to `void mergesortImproved::beginSorting<int>(std::vector<int, std::allocator<int> >&)'
collect2: error: ld returned 1 exit status

对于Linux机器:

>gcc -v
"crazy alphabet-soup pops up, followed by:"
Thread model: posix
gcc version 7.2.0 (x86_64-posix-seh-rev1, Built by MinGW-W64 project)

以下是我尝试的不同g ++调用:

请注意下面显示的控制台输出行:

所有错误响应最初都是非常长的单行输出。为了更容易阅读,我已经冒昧地将输出分成多行。

即,不必搜索$gcc -v "like windows, it starts with crazy alphabet-soup, followed by:" Thread model: posix gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4) 的位置,以及重复格式的其他视觉提示。

Linux尝试

  • Linux_attempt-1:

    undefined reference

    (我在上面的问题陈述中显示的错误相同)

  • Linux_attempt-2:

    $ g++ -o msI_out -std=c++17 *.cpp
    In function `generateTimeData(quicksort&, mergesort&, mergesortImproved&, int const&, long double&, std::vector<int, std::allocator<int> >&)':
    driver.cpp:(.text+0xaac): undefined reference to `void mergesortImproved::beginSorting<int>(std::vector<int, std::allocator<int> >&)'
    collect2: error: ld returned 1 exit status
    

    (我在上面的问题陈述中显示的错误相同)

  • Linux_attempt-3:

    $ g++ -o msI_out -std=c++17 driver.cpp quicksort.cpp  mergesortImproved.cpp mergesort.cpp WorkDir.cpp
    /tmp/ccQzfFiq.o: In function `generateTimeData(quicksort&, mergesort&, mergesortImproved&, int const&, long double&, std::vector<int, std::allocator<int> >&)':
    driver.cpp:(.text+0xaac): undefined reference to `void mergesortImproved::beginSorting<int>(std::vector<int, std::allocator<int> >&)'
    collect2: error: ld returned 1 exit status
    

Windows 10尝试

  • Windows_attempt-1:

    $ g++ -c -std=c++17 driver.cpp quicksort.cpp  mergesortImproved.cpp mergesort.cpp WorkDir.cpp
    $ g++ -o msI_out -std=c++17 driver.o quicksort.o mergesortImproved.o mergesort.o WorkDir.o
    driver.o: In function `generateTimeData(quicksort&, mergesort&, mergesortImproved&, int const&, long double&, std::vector<int, std::allocator<int> >&)':
    driver.cpp:(.text+0xaac): undefined reference to `void mergesortImproved::beginSorting<int>(std::vector<int, std::allocator<int> >&)'
    collect2: error: ld returned 1 exit status
    
  • Windows_attempt-2:

    >g++ -o msI_out -std=c++17 *.cpp
    \cc1alJ9m.o:driver.cpp:(.text+0x94f): undefined reference to `void mergesortImproved::beginSorting<int>(std::vector<int, std::allocator<int> >&)'
    collect2.exe: error: ld returned 1 exit status
    
  • Windows_attempt-3:

    >g++ -o msI_out -std=c++17 driver.cpp mergesort.cpp quicksort.cpp mergesortImproved.cpp WorkDir.cpp
    \ccGBGXAX.o:driver.cpp:(.text+0x94f): undefined reference to `void mergesortImproved::beginSorting<int>(std::vector<int, std::allocator<int> >&)'
    collect2.exe: error: ld returned 1 exit status
    

查看文件

  1. driver.cpp
  2. mergesortImproved.h
  3. mergesortImproved.cpp
  4. driver.cpp

    >g++ -c -std=c++17 driver.cpp quicksort.cpp  mergesortImproved.cpp mergesort.cpp WorkDir.cpp
    >g++ -o msI_out -std=c++17 driver.o quicksort.o mergesortImproved.o mergesort.o WorkDir.o
    driver.o:driver.cpp:(.text+0x94f): undefined reference to `void mergesortImproved::beginSorting<int>(std::vector<int, std::allocator<int> >&)'
    collect2.exe: error: ld returned 1 exit status
    

    mergesortImproved.h

        // driver.cpp 
    
    #include <iostream>
    #include <vector>
    #include "mergesortImproved.h"     
    
    using namespace std;
    
    /** int main( int argc, char *argv[] )
     *
     * main(arc, argv) will perform the task of initializing sorting classes, output files, and control variables.
     *
     *
     * @param argc      The number of arguments passed on the command line.
     *                  If argc == 1, then no additional arguments were passed, as the first argument is always the
     *                  name of the executable file.
     *
     * @param argv      An array of c_strings containing any command-line arguments beyond the initial executable's name.
     * @return          the error code should any be thrown, otherwise 0 when all goes well.
     */
    int main( int argc, char *argv[] )
    {   
     vector<int> sampleVector = {41,  8467,  6334,  6500,  9169,  5724,  1478,  9358,  6962, 4464,  5705,  8145,  3281,  6827};      
      mergesortImproved msI;
      msI.beginSorting(sampleVector);
      return 0;
    }
    

    mergesortImproved.cpp

    #ifndef MSI_ASSIG4_MERGESORTIMPROVED_H
    #define MSI_ASSIG4_MERGESORTIMPROVED_H
    
    #include <iostream>
    #include <vector>
    #include <stack>
    #include <queue>
    
    using namespace std;
    class mergesortImproved
    {
    public:
    
    /** template<class Comparable> void beginSorting(vector<Comparable> &data)
        *
        * Handles preparations for iterative-in-place Mergesort. Namely, the math needed for locating and saving index pointers into
        * queues and stacks that will later be used to emulate recursively subdeviding the unsorted collection before the much
        * simpler task of recombining the imaginary subdivisions.
        *
        * @tparam Comparable   This template reference is meant for use with data types that possess natural ordering.
        *                      Although there are no assert restrictions in place to ensure you only use data types with natural
        *                      ordering, the problem should become quickly apparant if the programmer fails to respect this
        *                      requirement.
        *
        * @param data          The vector<Comparable> that is to be sorted
        */
        template<class Comparable>
        void beginSorting(vector<Comparable> &vector);
    
    /** template <class Comparable> mergesortImproved(vector<Comparable> &data)
        *
        * @tparam Comparable   This template reference is meant for use with data types that possess natural ordering.
        *                      Although there are no assert restrictions in place to ensure you only use data types with natural
        *                      ordering, the problem should become quickly apparant if the programmer fails to respect this
        *                      requirement.
        *
        * @param data          The vector<Comparable> that is to be sorted
        */
        template <class Comparable>
        mergesortImproved(vector<Comparable> &data)
        {
            beginSorting(data);
        }
    
        mergesortImproved()=default;
    
    private:
        // omitted
    };
    #endif //MSI_ASSIG4_MERGESORTIMPROVED_H
    

    最简单的解决方案示例

    1. driver.cpp
    2. mergesortImproved.h
    3. mergesortImproved.cpp
    4. driver.cpp

      (driver.cpp与以前完全没有变化,但是我已经在这里展示了它的代码,以便在看到事物如何结合在一起时视觉上的轻松。)

      #include "mergesortImproved.h"
      
      
      using namespace std;
      
      
      /** template<class Comparable> void beginSorting(vector<Comparable> &data)
      *
      * Handles preparations for iterative-in-place Mergesort. Namely, the math needed for locating and saving index pointers into
      * queues and stacks that will later be used to emulate recursively subdeviding the unsorted collection before the much
      * simpler task of recombining the imaginary subdivisions.
      *
      * @tparam Comparable   This template reference is meant for use with data types that possess natural ordering.
      *                      Although there are no assert restrictions in place to ensure you only use data types with natural
      *                      ordering, the problem should become quickly apparant if the programmer fails to respect this
      *                      requirement.
      *
      * @param data          The vector<Comparable> that is to be sorted
      */
      template<class Comparable>
      void mergesortImproved::beginSorting(vector<Comparable> &data)
      {
        // dummy functionality here, just demonstrating the conditions causing the linker error
        cout << "Hey, it's running!!" << endl;
      }
      

      mergesortImproved.h

          // driver.cpp 
      
      #include <iostream>
      #include <vector>
      #include "mergesortImproved.h"     
      
      using namespace std;
      
      /** int main( int argc, char *argv[] )
       *
       * main(arc, argv) will perform the task of initializing sorting classes, output files, and control variables.
       *
       *
       * @param argc      The number of arguments passed on the command line.
       *                  If argc == 1, then no additional arguments were passed, as the first argument is always the
       *                  name of the executable file.
       *
       * @param argv      An array of c_strings containing any command-line arguments beyond the initial executable's name.
       * @return          the error code should any be thrown, otherwise 0 when all goes well.
       */
      int main( int argc, char *argv[] )
      {   
       vector<int> sampleVector = {41,  8467,  6334,  6500,  9169,  5724,  1478,  9358,  6962, 4464,  5705,  8145,  3281,  6827};      
        mergesortImproved msI;
        msI.beginSorting(sampleVector);
        return 0;
      }
      

      mergesortImproved.cpp

      #ifndef MSI_ASSIG4_MERGESORTIMPROVED_H
      #define MSI_ASSIG4_MERGESORTIMPROVED_H
      
      #include <iostream>
      #include <vector>
      #include <stack>
      #include <queue>
      
      class mergesortImproved
      {
      
      public:
      
      /** template<class Comparable> void beginSorting(vector<Comparable> &data)
      *
      * Handles preparations for iterative-in-place Mergesort. Namely, the math needed for locating and saving index pointers into
      * queues and stacks that will later be used to emulate recursively subdeviding the unsorted collection before the much
      * simpler task of recombining the imaginary subdivisions.
      *
      * @tparam Comparable   This template reference is meant for use with data types that possess natural ordering.
      *                      Although there are no assert restrictions in place to ensure you only use data types with natural
      *                      ordering, the problem should become quickly apparant if the programmer fails to respect this
      *                      requirement.
      *
      * @param data          The vector<Comparable> that is to be sorted
      */
      template<class Comparable>
      void mergesortImproved::beginSorting(std::vector<Comparable> &data)
      {
        // dummy functionality here, just demonstrating the conditions causing the linker error
        cout << "Hey, it's running!!" << endl;
      }    
      
      
      /** template<class Comparable> void beginSorting(vector<Comparable> &data)
      *
      * Handles preparations for iterative-in-place Mergesort. Namely, the math needed for locating and saving index pointers into
      * queues and stacks that will later be used to emulate recursively subdeviding the unsorted collection before the much
      * simpler task of recombining the imaginary subdivisions.
      *
      * @tparam Comparable   This template reference is meant for use with data types that possess natural ordering.
      *                      Although there are no assert restrictions in place to ensure you only use data types with natural
      *                      ordering, the problem should become quickly apparant if the programmer fails to respect this
      *                      requirement.
      *
      * @param data          The vector<Comparable> that is to be sorted
      */
      template<class Comparable>
      void beginSorting(vector<Comparable> &vector);
      
      /** template <class Comparable> mergesortImproved(vector<Comparable> &data)
          *
          * @tparam Comparable   This template reference is meant for use with data types that possess natural ordering.
          *                      Although there are no assert restrictions in place to ensure you only use data types with natural
          *                      ordering, the problem should become quickly apparant if the programmer fails to respect this
          *                      requirement.
          *
          * @param data          The vector<Comparable> that is to be sorted
          */
          template <class Comparable>
          mergesortImproved(vector<Comparable> &data)
          {
              beginSorting(data);
          }
      
          mergesortImproved()=default;
      
      private:
          // omitted
      };
      #endif //MSI_ASSIG4_MERGESORTIMPROVED_H
      

0 个答案:

没有答案