报错重定义
- 解决方式:inline 函数( inline 标记一个函数时,允许编译单元中有相同签名的实体,最后链接时只保留一个。这样你就可以将函数的实现写在头文件里,而不用担心冲突了。而如果没有 inline 标记的函数,你把函数体写在头文件里,该头文件被多个源文件包含并使用时,链接时就会冲突。)
#include <iostream>
#include <string>
#include "tempalate.h"
int main() {
S1<int>(2.1);
S1<bool>(2.1);
S1<float>(2.1);
S1<double>(2.1);
std::cout << '\n';
int* p = new int(1);
std::cout << "getTypeName(p): " << getTypeName(p) << '\n';
std::cout << "getTypeName2(p): " << getTypeName2(p) << '\n';
std::cout << '\n';
delete p;
p = nullptr;
}
输出:
special int !
bool!
float!
double!
getTypeName(p): int pointer
getTypeName2(p): pointer
special int !
#pragma once
#include <iostream>
#include <typeinfo>
using namespace std;
template<typename T>
inline void S1(T num)
{
cout << typeid(T).name() << "!" << endl;
return;
}
template<>
inline void S1(int num)
{
cout << "special int !" << endl;
return;
}
template<typename T> // (1) - 主模板
inline std::string getTypeName(T)
{
return "unknown";
}
template<typename T> // (2) - 重载自 (1) 的主模板
inline std::string getTypeName(T*)
{
return "pointer";
}
template<> // (3) - (2) 的显式特例化
inline std::string getTypeName(int*)
{
return "int pointer";
}
// getTypeName2
template<typename T> // (4) - 主模板
inline std::string getTypeName2(T) {
return "unknown";
}
template<> // (5) - (4) 的显式特例化
inline std::string getTypeName2(int*) {
return "int pointer";
}
template<typename T> // (6) - 重载自 (4) 的主模板
inline std::string getTypeName2(T*) {
return "pointer";
}
拓展
- 类函数默认内联
- 函数模板的特例化不参与重载
- 由于模板不是函数,只是一些C++编译器指令,说明了如何生成类和成员函数定义,无法单独编译成
obj
文件,因此不能将模板成员函数放在独立的实现文件中。