typedef 向前声明_模板链接与前置声明引发的血案

本文分析了C++模板在使用时遇到的类型推导问题,具体表现为类模板根据不同的模板类型参数实例化了不同的泛型函数子,导致在不同模块中结果不一致。问题源于`SUPERSUBCLASS`宏的推导结果不同。通过`objdump`工具,展示了编译器如何处理模板实例化,并解释了`Child *`和`VisibleChild *`类型的推导差异。解决方案是通过类型萃取技法,确保模板类型参数提供完整的类型信息,避免依赖于前置声明。
摘要由CSDN通过智能技术生成

模板链接与前置声明引发的血案

现象:

有一个类模板,它会根据模板类型参数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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值