我正在设计一个C++静态库。我想让这些类成为泛型/可配置类,这样它们就可以支持许多数据类型(并且我不想在我的库中编写任何特定于数据类型的代码)。所以我已经模板化了这些类。
但是由于我目前使用的编译器不支持C++“导出”模板特性,所以我不得不在头文件中提供类的实现。我不想将我的类的实现细节暴露给将要使用我的库的客户端代码。
您能为我提供一些解决上述问题的设计方案吗?
发布于 2009-07-18 15:11:07
在模板出现之前,必须使用运行时多态性编写与类型无关的C++代码。但是对于模板,您也可以将这两种技术结合起来。
例如,假设您想要存储任何类型的值,以便以后检索。如果没有模板,您将不得不这样做:
struct PrintableThing
{
    // declare abstract operations needed on the type
    virtual void print(std::ostream &os) = 0;
    // polymorphic base class needs virtual destructor
    virtual ~PrintableThing() {}
};
class PrintableContainer
{
    PrintableThing *printableThing;
public:
    // various other secret stuff
    void store(PrintableThing *p);
};这个库的用户将不得不手工编写他们自己的PrintableThing派生版本,以包装自己的数据并在其上实现print函数。
但您可以在这样的系统周围包装一个基于模板的层:
template <T>
struct PrintableType : PrintableThing
{
    T instance;
    virtual void print(std::ostream &os)
        { os << instance; }
    PrintableType(const T &i)
        : instance(i) {}
};并在库的头部、PrintableContainer类的声明中添加一个方法:
template <class T>
void store(const T &p)
{
    store(new PrintableType(p));
}这充当了模板和运行时多态性之间的桥梁,编译时绑定到实现print的<<操作符,也绑定到复制构造函数(当然也转发到嵌套实例的析构函数)。
通过这种方式,您可以完全基于运行时多态性编写一个库,其实现能够隐藏在库的源代码中,但需要添加一点模板“糖”以方便使用。
这是否值得麻烦,将取决于您的需求。它有一个纯粹的技术优势,即运行时多态性本身就是您所需要的。不利的一面是,你无疑会降低编译器有效内联的能力。从好的方面来说,你的编译时间和二进制代码膨胀可能会下降。
例如std::tr1::function和boost::any,它们有一个非常干净、现代的基于C++模板的前端,但在后台作为运行时多态容器工作。
发布于 2009-07-18 16:35:25
我有个消息要告诉你,伙计。即使使用export,您仍然必须发布所有模板代码-- export使您不必将定义放在头文件中。你完全被卡住了。您可以使用的唯一技术是将一些非模板函数拆分出来,并将它们放入不同的类中。但这很难看,而且通常涉及void*、placement new和delete。这就是野兽的本性。
发布于 2009-07-18 14:00:29
你可以尝试混淆你的代码--但是除了在头文件中包含模板代码之外,你在C++03中几乎别无选择。
Vandevoorde在他的书中描述了另一种技术:显式实例化-但这需要显式实例化所有可能的有用组合。
但要对此主题进行最全面的回顾,请阅读C++模板:完整指南中的第6章。
编辑(回应您的评论):在不使用模板的情况下编写泛型代码有两种选择:
1)预处理器-仍需要头文件
2)使用void* - yuk -非常不安全
所以不,我不建议不使用模板来解决专门设计的问题(尽管有一些缺陷)。
https://stackoverflow.com/questions/1147588
复制相似问题