我对模板类有疑问。 例如,参加这个课程
template<class TBase> class CTemplateInherit : public TBase
{
public:
virtual void DoNonSpecializedWork();
virtual void DoTemplateWork();
virtual ~CTemplateInherit();
};
// In header file
template<class TBase>
bool CTemplateInherit<TBase>::DoTemplateWork()
{
std::wcout << L"CTemplateInherit::DoTemplateWork" << std::endl;
TBase::DoWork();
return true;
}
// In CPP file
bool CTemplateInherit::DoNonSpecializedWork()
{
std::wcout << L"CTemplateInherit::DoNonSpecializedWork" << std::endl;
return true;
}
现在,我希望能够使用dllexport在CPP文件中定义非专用方法,并且只保留标题中的特化。 通常情况下,我认为我可以将成员方法定义为模板化,但因为我从TBase继承是不可能的。
那么我怎么能分开呢?我只覆盖了TBase中的4个方法,并且希望能够将其他40个左右的方法保留为DLL中的DLLEXPORT,而专门化则位于头文件中。
提前感谢您的建议!
答案 0 :(得分:3)
如果您不想更改课程的hierarchy
。
1)specialize
您.cpp
文件中所有需要类型的函数。
template<>
bool CTemplateInherit<First>::DoNonSpecializedWork()
{
std::wcout << L"CTemplateInherit::DoNonSpecializedWork" << std::endl;
return true;
}
template<>
bool CTemplateInherit<Second>::DoNonSpecializedWork()
{
std::wcout << L"CTemplateInherit::DoNonSpecializedWork" << std::endl;
return true;
}
template<>
bool CTemplateInherit<Nth>::DoNonSpecializedWork()
{
std::wcout << L"CTemplateInherit::DoNonSpecializedWork" << std::endl;
return true;
}
2)使用
template<typename T>
bool CTemplateInherit<T>::DoNonSpecializedWork()
{
std::wcout << L"CTemplateInherit::DoNonSpecializedWork" << std::endl;
return true;
}
.cpp
文件中的,但在header
template class CTemplateInherit<First>;
template class CTemplateInherit<Second>;
template class CTemplateInherit<Nth>;
3) Dietmar 建议。
答案 1 :(得分:3)
我不太确定你要完成什么,但是在使用模板时,你需要确保在必要时实例化这些模板。当您将模板定义放在标头中时,您可以从编译器获得隐式实例化:每当它看到使用了一个函数模板并且该模板的定义可见时,它将实例化该模板。当您将模板放在其他位置时,编译器在需要时不会看到模板定义,因此不会隐式实例化它。但是,您可以自己实例化相应的功能模板,例如:
// In CPP file
template <class TBase>
bool CTemplateInherit<TBase>::DoNonSpecializedWork()
{
std::wcout << L"CTemplateInherit::DoNonSpecializedWork" << std::endl;
return true;
}
template bool CTemplateInherit<SomeBase>::DoNotSpecializeWork();
template bool CTemplateInherit<SomeOtherBase>::DoNotSpecializeWork();
答案 2 :(得分:1)
我认为缺少一条重要信息:非专业方法是否会覆盖TBase
类的虚拟方法?这是这里的核心问题。
如果没有,那么您可以为非专业方法创建另一个类,并从CTemplateInherit
类中的两个类继承(公开)。问题解决了。
但是,如果非专业方法覆盖了TBase类的虚方法,那么它只会稍微复杂一些:
解决方案1)获取所有非专用函数,并将它们重新组合成一个“细节”标题。作为一组(非模板)自由函数(如果它很容易将输入 - 输出作为参数传递)或作为(非模板)类与它所需的非专用数据成员。然后,在相应的cpp文件(稍后将编译到DLL中)中定义所有这些函数(实现它们)。
然后,在您的CTemplateInherit
类模板中,只需将非专用函数调用转发给“detail”函数集。由于模板默认为内联,因此开销为零。如果需要将“detail”函数重新组合成一个类(非模板),那么,只需使用private
继承,防止函数名冲突。然后,您可以像任何其他继承的数据成员一样访问“detail”类的数据成员,并且可以将非专用函数调用转发到可以编译为DLL的“detail”类实现(如果您有从DLL导出类的合适框架(因为普通的C ++没有可靠的机制),但你的问题似乎意味着你这样做。
此解决方案的唯一问题是烦人地创建了几个简单的转发功能。但恕我直言,这是一个合理的价格来支付隐藏DLL中的实现(几乎任何时候你想这样做,你最终写了一堆包装函数)。
解决方案2)如果基类中有一组非专用虚函数,那么该子集肯定不依赖于TBase
的实际类型(我的意思是,这些函数的原型可以是没有它而形成)。然后,这意味着您可以将该功能子集重新组合到另一个基类中,TBase
应该从该基类继承。我们称之为TNonSpecialBase
。此时,您可以设置以下层次结构:
class TNonSpecialBase {
// set of pure-virtual functions that are not special.
};
// this is an example of a class that could act as a TBase:
class TExampleBase : public virtual TNonSpecialBase {
// set of virtual functions that are special to TExampleBase.
};
class CNonSpecialDerived : public virtual TNonSpecialBase {
// declaration of non-specialized functions that override the function in TNonSpecialBase.
};
template <typename TBase>
class CTemplateInherit : public TBase, public CNonSpecialDerived {
// set of virtual functions that are specialized for the template argument TBase.
};
通过上面的设置,专用函数必须最终在CTemplateInherit
的头文件中,但在CNonSpecialDerived
重新分组的非专用函数可以在单独的cpp文件中定义(并编译)进入DLL)。这里的神奇技巧是使用虚拟继承来允许最终类具有基类TNonSpecialBase
的单个虚拟表。换句话说,这允许类CNonSpecialDerived
覆盖TBase中继承自TNonSpecialBase
的虚函数,只要TBase不覆盖任何这些函数(在这种情况下,编译器将调用它含糊不清)。这样,用户可以处理指向TBase
对象的指针,调用其任何虚函数,这将导致向CTemplateInherit
实现(专用)或CNonSpecialDerived
实现的调度(据推测,在DLL中)。