<legend id='Lm2I5'><style id='Lm2I5'><dir id='Lm2I5'><q id='Lm2I5'></q></dir></style></legend>

    • <bdo id='Lm2I5'></bdo><ul id='Lm2I5'></ul>
    <tfoot id='Lm2I5'></tfoot>
    <i id='Lm2I5'><tr id='Lm2I5'><dt id='Lm2I5'><q id='Lm2I5'><span id='Lm2I5'><b id='Lm2I5'><form id='Lm2I5'><ins id='Lm2I5'></ins><ul id='Lm2I5'></ul><sub id='Lm2I5'></sub></form><legend id='Lm2I5'></legend><bdo id='Lm2I5'><pre id='Lm2I5'><center id='Lm2I5'></center></pre></bdo></b><th id='Lm2I5'></th></span></q></dt></tr></i><div id='Lm2I5'><tfoot id='Lm2I5'></tfoot><dl id='Lm2I5'><fieldset id='Lm2I5'></fieldset></dl></div>

    <small id='Lm2I5'></small><noframes id='Lm2I5'>

        C++ 模板函数在头文件中编译但不是实现

        时间:2023-05-24
            <bdo id='MmyWv'></bdo><ul id='MmyWv'></ul>

            <tfoot id='MmyWv'></tfoot>

            <small id='MmyWv'></small><noframes id='MmyWv'>

                  <legend id='MmyWv'><style id='MmyWv'><dir id='MmyWv'><q id='MmyWv'></q></dir></style></legend>
                    <tbody id='MmyWv'></tbody>
                • <i id='MmyWv'><tr id='MmyWv'><dt id='MmyWv'><q id='MmyWv'><span id='MmyWv'><b id='MmyWv'><form id='MmyWv'><ins id='MmyWv'></ins><ul id='MmyWv'></ul><sub id='MmyWv'></sub></form><legend id='MmyWv'></legend><bdo id='MmyWv'><pre id='MmyWv'><center id='MmyWv'></center></pre></bdo></b><th id='MmyWv'></th></span></q></dt></tr></i><div id='MmyWv'><tfoot id='MmyWv'></tfoot><dl id='MmyWv'><fieldset id='MmyWv'></fieldset></dl></div>
                • 本文介绍了C++ 模板函数在头文件中编译但不是实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

                  问题描述

                  限时送ChatGPT账号..

                  我正在尝试学习模板,但遇到了这个令人困惑的错误.我在头文件中声明了一些函数,我想制作一个单独的实现文件,在其中定义函数.这是调用标头(dum.cpp)的代码:

                  I'm trying to learn templates and I've run into this confounding error. I'm declaring some functions in a header file and I want to make a separate implementation file where the functions will be defined. Here's the code that calls the header (dum.cpp):

                  #include <iostream>
                  #include <vector>
                  #include <string>
                  #include "dumper2.h"
                  
                  int main() {
                      std::vector<int> v;
                      for (int i=0; i<10; i++) {
                          v.push_back(i);
                      }
                      test();
                      std::string s = ", ";
                      dumpVector(v,s);
                  }
                  

                  现在,这是一个可用的头文件 (dumper2.h):

                  Now, here's a working header file (dumper2.h):

                  #include <iostream>
                  #include <string>
                  #include <vector>
                  
                  void test();
                  
                  template <class T> void dumpVector( std::vector<T> v,std::string sep);
                  
                  template <class T> void dumpVector(std::vector<T> v, std::string sep) {
                      typename std::vector<T>::iterator vi;
                  
                      vi = v.begin();
                      std::cout << *vi;
                      vi++;
                      for (;vi<v.end();vi++) {
                          std::cout << sep << *vi ;
                      }
                      std::cout << "
                  ";
                      return;
                  }
                  

                  使用实现(dumper2.cpp):

                  With implementation (dumper2.cpp):

                  #include <iostream>
                  #include "dumper2.h"
                  
                  void test() {
                      std::cout << "!olleh dlrow
                  ";
                  }
                  

                  奇怪的是,如果我将定义 dumpVector 的代码从 .h 移动到 .cpp 文件,我会收到以下错误.

                  The weird thing is that if I move the code that defines dumpVector from the .h to the .cpp file, I get the following error.

                  g++ -c dumper2.cpp -Wall -Wno-deprecated
                  g++ dum.cpp -o dum dumper2.o -Wall -Wno-deprecated
                  /tmp/ccKD2e3G.o: In function `main':
                  dum.cpp:(.text+0xce): undefined reference to `void dumpVector<int>(std::vector<int, std::allocator<int> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
                  collect2: ld returned 1 exit status
                  make: *** [dum] Error 1
                  

                  那么为什么它以一种方式工作而不是另一种方式?明明编译器能找到test(),为什么找不到dumpVector?

                  So why does it work one way and not the other? Clearly the compiler can find test(), so why can't it find dumpVector?

                  推荐答案

                  您遇到的问题是编译器不知道要实例化模板的哪个版本.当您将函数的实现移动到 x.cpp 时,它位于与 main.cpp 不同的翻译单元中,并且 main.cpp 无法链接到特定的实例化,因为它不存在于该上下文中.这是 C++ 模板的一个众所周知的问题.有几种解决方案:

                  The problem you're having is that the compiler doesn't know which versions of your template to instantiate. When you move the implementation of your function to x.cpp it is in a different translation unit from main.cpp, and main.cpp can't link to a particular instantiation because it doesn't exist in that context. This is a well-known issue with C++ templates. There are a few solutions:

                  1) 像之前一样,将定义直接放在 .h 文件中.这有优点 &缺点,包括解决问题(专业版),可能使代码的可读性降低在某些编译器上更难调试 (con) 并且可能会增加代码膨胀 (con).

                  1) Just put the definitions directly in the .h file, as you were doing before. This has pros & cons, including solving the problem (pro), possibly making the code less readable & on some compilers harder to debug (con) and maybe increasing code bloat (con).

                  2) 将实现放在 x.cpp 中,#include "x.cpp" 来自 x.h.如果这看起来很奇怪而且是错误的,请记住 #include 只会读取指定的文件并编译它就好像该文件是 x.cpp 换句话说,这与上面的解决方案#1 所做的完全一样,但它将它们保存在单独的物理文件中.在做这种事情时,重要的是不要试图自己编译 #included 文件.出于这个原因,我通常给这些类型的文件一个 hpp 扩展名,以将它们与 h 文件和 cpp 文件区分开来.

                  2) Put the implementation in x.cpp, and #include "x.cpp" from within x.h. If this seems funky and wrong, just keep in mind that #include does nothing more than read the specified file and compile it as if that file were part of x.cpp In other words, this does exactly what solution #1 does above, but it keeps them in seperate physical files. When doing this kind of thing, it is critical that you not try to compile the #included file on it's own. For this reason, I usually give these kinds of files an hpp extension to distinguish them from h files and from cpp files.

                  #include <iostream>
                  #include <string>
                  #include <vector>
                  
                  void test();
                  template <class T> void dumpVector( std::vector<T> v,std::string sep);
                  #include "dumper2.hpp"
                  

                  文件:dumper2.hpp

                  template <class T> void dumpVector(std::vector<T> v, std::string sep) {
                    typename std::vector<T>::iterator vi;
                  
                    vi = v.begin();
                    std::cout << *vi;
                    vi++;
                    for (;vi<v.end();vi++) {
                      std::cout << sep << *vi ;
                    }
                    std::cout << "
                  ";
                    return;
                  
                  }
                  

                  3) 由于问题在于尝试使用它的翻译单元不知道 dumpVector 的特定实例化,因此您可以在与定义模板的地方.只需添加: template void dumpVector(std::vector v, std::string sep); ... 到定义模板的文件中.这样做,您不再需要从 h 文件中#include hpp 文件:

                  3) Since the problem is that a particular instantiation of dumpVector is not known to the translation unit that is trying to use it, you can force a specific instantiation of it in the same translation unit as where the template is defined. Simply by adding this: template void dumpVector<int>(std::vector<int> v, std::string sep); ... to the file where the template is defined. Doing this, you no longer have to #include the hpp file from within the h file:

                  #include <iostream>
                  #include <string>
                  #include <vector>
                  
                  void test();
                  template <class T> void dumpVector( std::vector<T> v,std::string sep);
                  

                  文件:dumper2.cpp

                  template <class T> void dumpVector(std::vector<T> v, std::string sep) {
                    typename std::vector<T>::iterator vi;
                  
                    vi = v.begin();
                    std::cout << *vi;
                    vi++;
                    for (;vi<v.end();vi++) {
                      std::cout << sep << *vi ;
                    }
                    std::cout << "
                  ";
                    return;
                  }
                  
                  template void dumpVector<int>(std::vector<int> v, std::string sep);
                  

                  顺便说一句,总而言之,您的模板函数正在采用 vector by-value.您可能不想这样做,而是通过引用或指针传递它,或者更好的是,传递迭代器以避免创建临时 &复制整个向量.

                  By the way, and as a total aside, your template function is taking a vector by-value. You may not want to do this, and pass it by reference or pointer or, better yet, pass iterators instead to avoid making a temporary & copying the whole vector.

                  这篇关于C++ 模板函数在头文件中编译但不是实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!

                • <small id='JRvSh'></small><noframes id='JRvSh'>

                      1. <i id='JRvSh'><tr id='JRvSh'><dt id='JRvSh'><q id='JRvSh'><span id='JRvSh'><b id='JRvSh'><form id='JRvSh'><ins id='JRvSh'></ins><ul id='JRvSh'></ul><sub id='JRvSh'></sub></form><legend id='JRvSh'></legend><bdo id='JRvSh'><pre id='JRvSh'><center id='JRvSh'></center></pre></bdo></b><th id='JRvSh'></th></span></q></dt></tr></i><div id='JRvSh'><tfoot id='JRvSh'></tfoot><dl id='JRvSh'><fieldset id='JRvSh'></fieldset></dl></div>
                        <tfoot id='JRvSh'></tfoot>

                          <tbody id='JRvSh'></tbody>
                          <bdo id='JRvSh'></bdo><ul id='JRvSh'></ul>
                        • <legend id='JRvSh'><style id='JRvSh'><dir id='JRvSh'><q id='JRvSh'></q></dir></style></legend>