繁体   English   中英

模板类中的C ++非专业成员

[英]C++ non-specialized member in template class

我对模板类有疑问。 例如,参加这个课程

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中,而专门化条件位于头文件中。

提前感谢您的建议!

如果您不想更改类的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所建议。

我不太确定要尝试完成什么,但是在使用模板时,需要确保根据需要实例化这些模板。 将模板定义放在标头中时,可以从编译器获取隐式实例化:每当看到使用了功能模板且该模板的定义可见时,它将实例化该模板。 当您将模板放在其他位置时,编译器将在需要时看不到模板定义,因此不会隐式实例化它。 但是,您可以自己实例化相应的功能模板,例如:

// 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();

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

如果不是,则可以为非专用方法创建另一个类,并从CTemplateInherit类的两个类中(公共)继承。 问题解决了。

但是,如果非专用方法覆盖了TBase类的虚方法,那么它只会稍微复杂一点:

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

然后,在您的CTemplateInherit类模板中,只需将非专业化的函数调用转发到“详细”函数集即可。 因为默认情况下内联模板,所以开销为零。 如果需要将“详细信息”功能重新分组为一个类(非模板),则只需使用private继承即可,以防止功能名冲突。 然后,您可以像访问其他任何继承的数据成员一样访问“详细信息”类的数据成员,并且可以将非专门的函数调用转发到“详细信息”类实现,该实现可以编译为DLL(如果您有从DLL导出类的合适框架(因为普通的C ++没有可靠的机制),但是您的问题似乎暗示您已经这样做了。

该解决方案的唯一问题是烦人的几个简单转发功能的创建。 但是恕我直言,这是在DLL中添加实现的合理价格(几乎在任何时候想要这样做,最终都会编写大量包装函数)。

解决方案2)如果基类中存在一组非专业的虚函数,则该子集肯定不依赖于TBase的实际类型(我的意思是,这些函数的原型可以在没有它的情况下形成)。 然后,这意味着您可以将该函数的子集重新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的头文件中,但是可以在单独的cpp文件中定义在CNonSpecialDerived重组的非专用功能(并将其编译为DLL)。 这里的魔术是使用虚拟继承来允许最终类为基类TNonSpecialBase提供单个虚拟表。 换句话说,这允许类CNonSpecialDerived重写TBase中从TNonSpecialBase继承的虚拟函数,只要TBase不重写任何这些函数(在这种情况下,编译器将其称为歧义的)。 这样,用户可以处理指向TBase对象的指针,调用其任何虚拟函数,这将导致向CTemplateInherit实现(专用)或CNonSpecialDerived实现(可能在DLL中)的调度。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM