问题出现的背景
今天在写代码的时候,使用模板泛化,为了让类的代码封装更好,便将类的声明都放在了一个名为 heap.h
的头文件中,将实现的方法写到了 heap.cpp
文件中。
代码是一个大顶堆的数据结构。
问题说明
如下:
heap.h
#pragma once
#include <vector>
template <typename T>
class heap
{
public:
heap(std::vector<T> v);
~heap() {};
void insert_heap(T val);
T pop_heap();
private:
std::vector<T> a;
void make_heap();
void adjust_heap(int index);
};
heap.cpp:
#include "heap.h"
#include <vector>
using namespace std;
template <typename T>
heap<T>::heap(std::vector<T> v) : a(v) {
T tmp;
a.insert(a.begin(),tmp);
make_heap();
}
template <typename T>
void heap<T>::make_heap()
{
int length = a.size();
int deaf = length / 2; //取出第一个叶子节点
while (deaf>0) {
adjust_heap(deaf);
deaf--;
}
}
template <typename T>
void heap<T>::adjust_heap(int index)
{
int length = a.size();
while (index < length/2) {
if (index * 2 + 1 < length
&& a[index * 2] > a[index * 2 + 1]
&& a[index * 2] > a[index]) {
T tmp = a[index];
a[index] = a[index * 2];
a[index * 2] = tmp;
index = index * 2;
}
else if (index * 2 + 1 < length &&
a[index * 2] <= a[index * 2 + 1] &&
a[index * 2 + 1] > a[index]) {
T tmp = a[index];
a[index] = a[index * 2 + 1];
a[index * 2 + 1] = tmp;
index = index * 2 + 1;
}
else if (index * 2 + 1 == length && a[index * 2] > a[index])
{
T tmp = a[index];
a[index] = a[index * 2];
a[index * 2] = tmp;
break;
}
else
break;
}
}
template <typename T>
void heap<T>::insert_heap(T val) {
a.push_back(val);
int length = a.size() - 1;
while (length > 1)
{
if (a[length / 2] < a[length])
{
T tmp = a[length];
a[length] = a[length / 2];
a[length / 2] = tmp;
length = length / 2;
}
else
break; //当前节点小于等于父节点:终止
}
}
template<typename T>
T heap<T>::pop_heap() {
int length = a.size();
T tmp = a[1]; //将最大节点放到末尾
a[1] = a[length - 1];
a.pop_back();
adjust_heap(1);
return tmp;
}
main.cpp
#include "heap.h"
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> a = { 4,2,6,8,12,60,83,5 };
heap<int> test(a);
cout << test.pop_heap() << endl;
cout << test.pop_heap() << endl;
cout << test.pop_heap() << endl;
test.insert_heap(99);
cout << test.pop_heap() << endl;
system("pause");
return 0;
}
报出下面的编译错误:
源.obj : error LNK2019: 无法解析的外部符号 “public: __thiscall heap::heap(class std::vector<int,class std::allocator >)” (??0?heap@H@@QAE@V?heap@H@@QAE@V?heap@H@@QAE@V?vector@HV?KaTeX parse error: Expected group after '_' at position 93: … "public: void _̲_thiscall heap<…heap@H@@QAEXH@Z),该符号在函数 _main 中被引用
源.obj : error LNK2019: 无法解析的外部符号 “public: int __thiscall heap::pop_heap(void)” (?pop_heap@?$heap@H@@QAEHXZ),该符号在函数 _main 中被引用
1>D:\2. MyProject\c++剑指offer\剑指offer2\Debug\heap.exe : fatal error LNK1120: 3 个无法解析的外部命令
遇到这个问题刚开始是崩溃的,感觉自己写的明明没有问题,叫来了几个小伙伴都没有把问题解决掉,因为大家平时写泛化类都是写到一个h文件中,今天差了一下午才找到解决问题的方法:
问题的解决
类的声明和实现,分别在不同的文件下,需要增加一个hpp文件支持。或者尽量将模板函数与模板友元放在一个文件下。
- 类的声明与函数的声明写在.h文件
- 类的实现及函数的实现写在.cpp文件
- 将.cpp文件改成.hpp文件
- 在主函数中调用.hpp文件,而不是引用.h文件
于是将 heap.cpp
改成 heap1.hpp
编译通过,注意:mian.cpp 中引用 heap1.hpp