2

我有一个关于模板类的问题。例如,上这堂课

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 个左右的方法作为 DLLEXPORT 保留在 DLL 中,而专门化在头文件中。

提前感谢您的建议!

4

3 回答 3

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) 正如迪特玛建议的那样。

于 2012-09-02T13:14:20.440 回答
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();
于 2012-09-02T13:21:23.940 回答
1

我认为缺少一条重要信息:非专业方法是否覆盖了TBase类的虚拟方法?这是这里的中心问题。

如果没有,那么您可以为非专业方法创建另一个类,并从您的CTemplateInherit类中的两个类(公开)继承。问题解决了。

然而,如果非特化方法覆盖了 TBase 类的虚方法,那么它只会稍微复杂一些:

解决方案 1) 将所有非专用函数重新组合到一个“详细”标题中。作为一组(非模板)自由函数(如果将输入输出作为参数传递足够容易的话)或作为具有它所需的非专业数据成员的(非模板)类。然后,在相应的 cpp 文件(稍后将其编译到 DLL 中)中定义所有这些函数(实现它们)。

然后,在您的CTemplateInherit类模板中,只需将非专用函数调用转发到“详细”函数集。因为模板默认内联,所以开销为零。如果您需要将“详细”函数重新组合到一个类(非模板)中,那么只需使用private继承,防止函数名冲突。然后,您可以像访问任何其他继承的数据成员一样访问“详细”类的数据成员,并且可以将非专用函数调用转发到可以编译成 DLL 的“详细”类实现(如果您有适合从 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 中)。

于 2012-09-02T15:14:30.597 回答