将模板化的C ++类分割为.hpp / .cpp文件 - 是可能吗? [英] Splitting templated C++ classes into .hpp/.cpp files--is it possible?

查看:377
本文介绍了将模板化的C ++类分割为.hpp / .cpp文件 - 是可能吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我收到错误尝试编译一个C ++模板类,它分为 .hpp .cpp 文件:

I am getting errors trying to compile a C++ template class which is split between a .hpp and .cpp file:

$ g++ -c -o main.o main.cpp  
$ g++ -c -o stack.o stack.cpp   
$ g++ -o main main.o stack.o  
main.o: In function `main':  
main.cpp:(.text+0xe): undefined reference to 'stack<int>::stack()'  
main.cpp:(.text+0x1c): undefined reference to 'stack<int>::~stack()'  
collect2: ld returned 1 exit status  
make: *** [program] Error 1  

stack.hpp

#ifndef _STACK_HPP
#define _STACK_HPP

template <typename Type>
class stack {
    public:
            stack();
            ~stack();
};
#endif

stack.cpp

#include <iostream>
#include "stack.hpp"

template <typename Type> stack<Type>::stack() {
        std::cerr << "Hello, stack " << this << "!" << std::endl;
}

template <typename Type> stack<Type>::~stack() {
        std::cerr << "Goodbye, stack " << this << "." << std::endl;
}

main.cpp

#include "stack.hpp"

int main() {
    stack<int> s;

    return 0;
}

ld 程序正确:符号不在 stack.o

ld is of course correct: the symbols aren't in stack.o.

这个问题没有帮助,因为我已经在做它说的。

可能有帮助,但我不想将每一个方法移动到 .hpp / / 1111440 / undefined-reference-error-for-template- / code> file—我不应该,我应该吗?

The answer to this question does not help, as I'm already doing as it says.
This one might help, but I don't want to move every single method into the .hpp file—I shouldn't have to, should I?

是移动中的一切的唯一合理的解决方案。 cpp文件到 .hpp 文件,只是包含所有内容,而不是作为一个独立的目标文件链接?这似乎可怕丑陋!在这种情况下,我可以还原到我之前的状态,并将 stack.cpp 重命名为 stack.hpp 完成。

Is the only reasonable solution to move everything in the .cpp file to the .hpp file, and simply include everything, rather than link in as a standalone object file? That seems awfully ugly! In that case, I might as well revert to my previous state and rename stack.cpp to stack.hpp and be done with it.

推荐答案

不可能在单独的cpp文件中编写模板类的实现并编译。所有的方法,如果有人声称,是模仿单独的cpp文件的使用的解决方法,但实际上如果你打算写一个模板类库和分发它的头文件和lib文件隐藏的实现,这是根本不可能。

It is not possible to write the implementation of a template class in a separate cpp file and compile. All the ways to do so, if anyone claims, are workarounds to mimic the usage of separate cpp file but practically if you intend to write a template class library and distribute it with header and lib files to hide the implementation, it is simply not possible.

要知道为什么,让我们来看看编译过程。头文件从不编译。它们只是预处理。然后预处理的代码与实际编译的cpp文件clubbed。现在如果编译器必须为对象生成适当的内存布局,那么它需要知道模板类的数据类型。

To know why, let us look at the compilation process. The header files are never compiled. They are only preprocessed. The preprocessed code is then clubbed with the cpp file which is actually compiled. Now if the compiler has to generate the appropriate memory layout for the object it needs to know the data type of the template class.

实际上,必须理解,模板类不是一个类,而是一个类的模板,它的声明和定义是由编译器在编译时生成的从参数获取数据类型的信息。只要无法创建内存布局,就无法生成方法定义的说明。记住类方法的第一个参数是'this'运算符。所有类方法都转换为具有名称调整的单个方法,第一个参数作为它操作的对象。 'this'参数实际上告诉了对象的大小,其中模板类不能用于编译器,除非用户实例化具有有效类型参数的对象。在这种情况下,如果你把方法定义放在一个单独的cpp文件,并尝试编译它的目标文件本身不会与类信息生成。编译不会失败,它会生成目标文件,但不会为目标文件中的模板类生成任何代码。这就是为什么链接器无法找到对象文件中的符号,并且构建失败的原因。

Actually it must be understood that template class is not a class at all but a template for a class the declaration and definition of which is generated by the compiler at compile time after getting the information of the data type from the argument. As long as the memory layout cannot be created, the instructions for the method definition cannot be generated. Remember the first argument of the class method is the 'this' operator. All class methods are converted into individual methods with name mangling and the first parameter as the object which it operates on. The 'this' argument is which actually tells about size of the object which incase of template class is unavailable for the compiler unless the user instantiates the object with a valid type argument. In this case if you put the method definitions in a separate cpp file and try to compile it the object file itself will not be generated with the class information. The compilation will not fail, it would generate the object file but it won't generate any code for the template class in the object file. This is the reason why the linker is unable to find the symbols in the object files and the build fails.

现在,隐藏重要实现细节的替代方法是什么?因为我们都知道分离接口与实现背后的主要目的是以二进制形式隐藏实现细节。这就是您必须分离数据结构和算法的地方。您的模板类必须仅表示数据结构而不是算法。这使您可以在单独的非模板化类库中隐藏更有价值的实现细节,其中的类将在模板类上工作,或者仅仅使用它们来保存数据。模板类实际上包含较少的代码来分配,获取和设置数据。其余的工作将由算法类完成。

Now what is the alternative to hide important implementation details? As we all know the main objective behind separating interface from implementation is hiding implementation details in binary form. This is where you must separate the data structures and algorithms. Your template classes must represent only data structures not the algorithms. This enables you to hide more valuable implementation details in separate non-templatized class libraries, the classes inside which would work on the template classes or just use them to hold data. The template class would actually contain less code to assign, get and set data. Rest of the work would be done by the algorithm classes.

我希望这次讨论会有所帮助。

I hope this discussion would be helpful.

这篇关于将模板化的C ++类分割为.hpp / .cpp文件 - 是可能吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆