一个C++模板有意思的小实验

看面经遇到一个C++模板的问题,顺手做了下实验看看结果,觉得比较有意思就记录一下


我们一般用模板会把声明和定义放在一起(放在同一个头文件内),那么如果我们在一个头文件内声明我们要使用的模板函数,并在另一个cpp文件内实现会怎么样?

// funcT.h
#pragma once
#include <iostream>

template<typename T>
void func2(T const& a, T const& b);
// funcT.cpp
#include "funcT.h"
#include <iostream>

template<typename T>
void func2(T const & a, T const & b)
{
    T c = a + b;
    std::cout << "func4" << std::endl;
    return ;
}

g++ -c funcT.cpp -o funcT 编译一下,没问题。

在另一个文件内使用函数

// main.cpp
#include <iostream>
#include "funcT.h"

int main()
{
    int x = 3;
    int y = 2;
    func2(x, y);

    return  0;
}

g++ -c main.cpp -o main 编译一下也没问题。

然后我们将两个目标文件链接为一个可执行文件,很遗憾报错了,具体错误是对 void func2<int>(int const&, int const&) 未定义的引用

这是为什么呢,我们明明已经给了一个具体的定义,为什么链接器找不到呢。

我们在 func.cpp 中加一段代码

// funcT.cpp
#include "funcT.h"
#include <iostream>

template<typename T>
void func2(T const & a, T const & b)
{
    T c = a + b;
    std::cout << "func4" << std::endl;
    return ;
}

void caller()  {
    func2(3, 4);
}

再编译->汇编->链接,不报错了,且能正常输出结果。

本质原因是模板是需要在编译的时候展开的,本身就不能算是“声明/定义”,或者说只是模板的声明和定义,而没有具体函数的定义,我们编译 func2.cpp,对于第一个版本,里面没有调用 func2(T const& a, T const& b) 的代码,所以编译器没有展开模板的任何实现。所以,我们在 main.cpp 中调用的时候,展开的只是一个声明,定义是缺失的,所以链接的时候会报错。

而第二个版本,我们在 func2.cpp 中加入了一个 caller 函数,里面实际调用了func2函数,所以在编译的时期生成了具体的函数定义,那么在链接的时候就能找到。

通过这个实验,更明确了模板展开是编译期行为。

另一个有意思的实验

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很高兴为您回答这个问题。以下是关于C++模板与异常的实验报告: 一、实验目的 通过实验,掌握C++模板和异常的使用方法,提高编程技能。 二、实验内容 1. 实现一个模板类,可以实现数组的基本操作,并能够处理异常情况。 2. 实现一个函数模板,可以实现两个数的交换,并能够处理异常情况。 三、实验步骤及方法 1. 实现模板类 (1)定义一个模板类,包含数组的大小和指向数组素的指针。 (2)实现数组基本操作,包括初始化数组、释放数组、获取数组素等。 (3)使用try-catch语句,处理数组越界的异常情况。 2. 实现函数模板 (1)定义一个函数模板,可以实现两个数的交换。 (2)使用try-catch语句,处理类型不匹配的异常情况。 四、实验结果 1. 实现模板模板类的定义如下: ```c++ template<typename T> class Array { public: Array(int size); ~Array(); T & operator[](int i); private: T * m_ptr; int m_size; }; ``` 模板类的实现如下: ```c++ template<typename T> Array<T>::Array(int size) { m_size = size; m_ptr = new T[size]; } template<typename T> Array<T>::~Array() { delete [] m_ptr; } template<typename T> T & Array<T>::operator[](int i) { if (i < 0 || i >= m_size) { throw std::out_of_range("Index out of range."); } return m_ptr[i]; } ``` 2. 实现函数模板 函数模板的定义如下: ```c++ template<typename T> void swap(T & a, T & b); ``` 函数模板的实现如下: ```c++ template<typename T> void swap(T & a, T & b) { T temp = a; a = b; b = temp; } ``` 五、实验总结 通过本次实验,我学会了如何使用C++模板和异常,这对我的编程技能提高有很大帮助。同时,我也发现了异常处理的重要性,可以有效地避免程序崩溃的情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值