模板链接与前置声明引发的血案
现象:
有一个类模板,它会根据模板类型参数T的实际类型,调用不同的实例化泛型函数子去处理实际事情。在程序运行时,发现在不同的模块中用相同的类型参数来调用该类模板,得到的结果不一致,也就是说在传入同样的实际模板类型参数实例化了不同的泛型函数子。因此,可以推测在不同的模块中对同样的实际模板类型参数作了不一样的处理,导致生成了不一样的实例化。
问题原型:
为了方便描述,我写了一个能重现这个问题的简化版原型:点此下载源码
模板参数类型类
Base类:
// Base.h
//
class Base {
public:
virtual ~Base();
virtual const char* GetName();
};
// Base.cpp
//
#include "Base.h"
Base::~Base() {
}
const char* Base::GetName()
{
return "Base";
}
Child类:
// Child.h
//
#include "Base.h"
class Child : public Base
{
public:
virtual const char* GetName();
};
// Child.cpp
//
#include "Child.h"
const char* Child::GetName()
{
return "Child";
}
VisibleChild类:
// VisibleChild.h
//
#include "Base.h"
class VisibleChild : public Base
{
public:
virtual const char* GetName();
};
// VisibleChild.cpp
//
#include "VisibleChild.h"
const char* VisibleChild::GetName()
{
return "VisibleChild";
}
使用类模板的类
UsingBase类:
// UsingBase.h
//
#include "Template.h"
#include "Base.h"
class Child;
class VisibleChild;
class UsingBase {
public:
void Use();
private:
void Print(Holder * holder);
void Print(Holder * holder);
void Print(Holder * holder);
};
// UsingBase.cpp
//
#include "UsingBase.h"
#include "VisibleChild.h"
void UsingBase::Print(Holder * holder)
{
holder->Print();
}
void UsingBase::Print(Holder * holder)
{
holder->Print();
}
void UsingBase::Print(Holder * holder)
{
holder->Print();
}
void UsingBase::Use()
{
printf("\n=== UsingBase::Use() ===\n");
Base* base = new Base();
Holder* hb = new Holder(base);
Print(hb);
delete base;
delete hb;
VisibleChild* visibleChild = new VisibleChild();
Holder* hc2 = new Holder(visibleChild);
Print(hc2);
delete visibleChild;
delete hc2;
}
UsingChild类:
// UsingChild.h
//
#include "Template.h"
class Child;
class VisibleChild;
class UsingChild {
public:
void Use();
private:
void Print(Holder * holder);
void Print(Holder * holder);
};
// UsingChild.cpp
//
#include "UsingChild.h"
#include "Child.h"
#include "VisibleChild.h"
void UsingChild::Print(Holder * holder)
{
holder->Print();
}
void UsingChild::Print(Holder * holder)
{
holder->Print();
}
void UsingChild::Use()
{
printf("\n=== UsingChild::Use() ===\n");
Child* child = new Child();
Holder* hc = new Holder(child);
Print(hc);
delete child;
delete hc;
VisibleChild* visibleChild = new VisibleChild();
Holder* hc2 = new Holder(visibleChild);
Print(hc2);
delete visibleChild;
delete hc2;
}
类模板:
// Template.h
//
#include
#include "Base.h"
// Helper types Small and Big - guarantee that sizeof(Small) < sizeof(Big)
//
template
struct ConversionHelper
{
ty