c++模板类的使用,编译的问题

前两天在写代码时,把模板类的声明和分开放在两个文件中了,类似于下面这样:

stack.hpp:

#ifndef _STACK_HPP
#define _STACK_HPP

template
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;
}
</type></typename></type></typename></iostream>

main.cpp

#include "stack.hpp"

int main() {
    stack s;

    return 0;
}
$ 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::stack()'
main.cpp:(.text+0x1c): undefined reference to 'stack::~stack()'
collect2: ld returned 1 exit status
make: *** [program] Error 1

提示找不到函数的定义

在网上寻找的答案如下:

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.

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.

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.

具体原因就是:

模板类其实就不是一个类,c++的编译器在编译.cpp产生二进制目标文件的时候,需要根据函数的参数类型来确定链接符号(编译器不编译.h文件),而编译模板类的时候因为函数的参数类型都没有确定,所以也就不能产生链接符号,所以在编译阶段是不会报错的,但是在链接阶段就报错了。针对这种情况有三种解决办法,但是最优的还是把实现和声明都放在头文件中。如果不想让c++类显得臃肿,可以在类里面声明,在类外进行实现。

参考链接

Original: https://www.cnblogs.com/xutopia/p/15715756.html
Author: xutopia
Title: c++模板类的使用,编译的问题

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/611220/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • [极客大挑战 2019]Secret File

    0x01 寻找做题信息 打开环境,查看源代码,发现可疑链接,/Archive_room.php,action.php打开action.php会发生302跳转,查找302跳转无果,百…

    Linux 2023年6月8日
    0104
  • mysql二进制安装脚本部署

    mysql二进制安装脚本部署 mysql二进制安装脚本部署 单实例 使用函数的单实例 使用函数的单实例或者多实例 单实例 [root@localhost ~]# mkdir mys…

    Linux 2023年6月6日
    0120
  • LVS负载均衡

    LVS负载均衡 LVS负载均衡 一、LVS是什么 二、LVS的作用 三、lvs的三种工作模式 1.基于NAT的LVS模式负载均衡 2.基于TUN模式的LVS负载均衡 3.LVS(D…

    Linux 2023年6月6日
    099
  • margin-top塌陷

    一、问题描述 ​ 在两个及以上的盒子嵌套时候,内部的盒子设置的 margin-top 的效果会加到最外边的盒子上,导致内部的盒子margin-top设置失败。 – 示例…

    Linux 2023年6月14日
    0111
  • .NET 6上的WebView2体验

    上次说为了不想在web端登录博客园,我想着还是继续使用 MarkWord编写博客,不过在使用的过程中,如果markdown文件的目录中有中文的话,Markdown预览就不能够显示粘…

    Linux 2023年6月6日
    0114
  • 自己写的文件夹图标修改脚本

    自己写了一个文件图标修改的Python脚本,只要把文件夹拖动到这个脚本上,就可以用文件夹中的图片和视频作为文件夹的封面。把图片或视频拖到脚本上,就可以把这个图片或视频用作其所在文件…

    Linux 2023年6月6日
    0166
  • 面试题:深拷贝、浅拷贝、引用拷贝的区别

    引用拷贝 浅拷贝 深拷贝 小结 作者:小牛呼噜噜 | https://xiaoniuhululu.com计算机内功、JAVA底层、面试相关资料等更多精彩文章在公众号「小牛呼噜噜 」…

    Linux 2023年6月6日
    0104
  • 自动化集成:Jenkins管理工具详解

    前言:该系列文章,围绕持续集成:Jenkins+Docker+K8S相关组件,实现自动化管理源码编译、打包、镜像构建、部署等操作; 本篇文章主要描述Jenkins基础用法。 一、J…

    Linux 2023年5月27日
    0114
  • JAVA设计模式-单例模式

    JAVA设计模式-单例模式 单例模式 类只能有一个实例,在内存中会创建并且只创建一次对象。所有其他类或者其他需要调用的地方都是用这一个对象,可以防止频繁创建对象,内存占用高。特点:…

    Linux 2023年6月6日
    0103
  • SpringBoot + Vue + ElementUI 实现后台管理系统模板 — 后端篇(三): 整合阿里云 OSS 服务 — 上传、下载文件、图片

    (1) 相关博文地址: SpringBoot + Vue + ElementUI 实现后台管理系统模板 — 前端篇(一):搭建基本环境:https://www.cnblogs.c…

    Linux 2023年6月11日
    087
  • 05-ElasticSearch高级搜索

    * package com.coolman.hotel.test; import com.coolman.hotel.pojo.HotelDoc; import com.faste…

    Linux 2023年6月7日
    0118
  • 生成随机数的若干种方法

    背景: 创建账户时我们需要配置初始随机密码,使用手机号注册时需要随机验证码,抽奖活动需要随机点名,俄罗斯方块游戏需要随机出形状。这些案例都在说明一个问题,随机数据很重要!而在 Sh…

    Linux 2023年6月6日
    095
  • MySQL——用户和权限管理

    由用户名和主机名组成 格式:’user_name’@’host’ host必须要用引号括起来 注意:host可以是一个主机名也可以是…

    Linux 2023年6月7日
    0100
  • jmeter 函数之 _RandomString

    jmeter中有许多函数,学会函数的灵活使用,对于很多工作都是事半功倍的效果,今天先学习函数——__RandomString,该函数可以自定义字符长度。做接口自动化测试时,可以使用…

    Linux 2023年6月8日
    0126
  • redis 基于SpringBoot Reids 的工具类

    redis 基于SpringBoot Reids 的工具类 package com.mhy.springredis.utils; import org.springframewor…

    Linux 2023年6月7日
    0123
  • 魔域来了H5游戏详细图文架设教程

    前言 想体验热血传奇的战场吗?想体验满级VIP的尊贵吗?想体验榜一大佬的无敌寂寞吗?各种极品炫酷时装、坐骑、翅膀、宠物通通给你,就在魔域来了H5! 本文讲解魔域来了架设教程,想研究…

    Linux 2023年6月7日
    0122
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球