Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C+中包装多个库的策略+;_C++_Wrapper_Abstraction - Fatal编程技术网

C++ 在C+中包装多个库的策略+;

C++ 在C+中包装多个库的策略+;,c++,wrapper,abstraction,C++,Wrapper,Abstraction,我有一个类Foo,它不是直接实现的,而是包装外部库(例如footexternal1或footexternal2) 我看到的一种方法是使用预处理器指令作为 #include "config.h" #include "foo.h" #ifdef _FOOXTERNAL1_WRAPPER_ //implementation of class Foo using FooXternal1 #endif #ifdef _FOOXTERNAL2_WRAPPER_ //implementation of cl

我有一个类
Foo
,它不是直接实现的,而是包装外部库(例如
footexternal1
footexternal2
) 我看到的一种方法是使用预处理器指令作为

#include "config.h"
#include "foo.h"
#ifdef _FOOXTERNAL1_WRAPPER_
//implementation of class Foo using FooXternal1
#endif

#ifdef _FOOXTERNAL2_WRAPPER_
//implementation of class Foo using FooXternal2
#endif
使用
config.h
定义这些预处理器标志(
\u footexternal1\u WRAPPER\u
\u footexternal2\u WRAPPER\u
)。 我认为C++程序员社区对此感到不快,因为它使用预处理器指令,调试困难等。此外,它不允许并行实现两种实现。 我考虑将
Foo
作为一个基类,并从中继承,以允许两个实现并行存在。但我遇到了两个问题:

  • 纯虚拟函数:
    无法恢复“Foo”类型的对象
    ,这是我在使用过程中需要的
  • 虚拟函数有运行没有(正确)实现的对象的风险
  • 我错过什么了吗?有没有更干净的方法

    编辑:总结一下,有3种(.5)包装方法-2种(.5)由icepack给出,最后一种由Sergey给出 1-使用工厂方法 2-使用预处理器指令 2.5-使用makefile或IDE有效地完成预处理器指令的工作 3.5-使用Sergay建议的模板


    我在一个资源有限的嵌入式系统上工作,我决定使用
    模板
    ,模板专门化。便于后期用户理解;至少我是这么认为的

    我唯一不赞成的是在同一个源文件中包含这两个实现。这可能会让人困惑。否则,这是预处理器标志擅长的事情之一,特别是如果您没有同时链接两个库。这就像支持多个操作系统一样。在所有情况下提供一致的接口,并将实现细节隐藏在其他地方

    type
    Foo
    是否需要保存每个库的特定信息?如果没有,您可能可以通过以下方式逃脱:

    #include "Foo.h"
    
    #if defined _FOOXTERNAL1_WRAPPER_
        #include "Foo_impl1.cpp"
    #elif defined _FOOXTERNAL2_WRAPPER_
        #include "Foo_impl2.cpp"
    #else
        #error "Warn about a missing define here"
    #endif
    

    这样,您就不必为虚拟函数或继承而烦恼,而且仍然可以防止任何成员函数无法实现。

    保持
    Foo
    抽象。提供工厂方法

    分配类型为
    FooImpl1
    FooImpl2
    的新对象,并返回其地址


    .

    如果外部实现的所有方法名称都相似,则可以使用模板。让外部实现看起来像:

    class FooX1
    {
    公众:
    void Met1()
    {
    
    std::cout如果您希望这两个实现在运行时共存,那么接口就是一种方法(例如,您可以使用工厂方法设计模式来实例化具体对象,如@n.m.所建议的)

    如果您可以在编译时决定需要什么样的实现,那么有几个选项:

    • 仍然使用接口。如果将来您在运行时需要这两种实现,这将允许轻松的转换

    • >P>使用预处理器指令。这里考虑到C++没有什么错误。这是一个纯粹的设计问题。

    • 将实现放在不同的文件中,并根据设置将编译器配置为编译其中任何一个-这实际上类似于使用预处理器指令,但它更干净,不会向代码中添加垃圾(因为标志位于解决方案/makefile/编译器使用的任何内容中)


    只要您链接两个外部库,提供一个虚拟类和两个具体类就是一个很好的解决方案——特别是在运行时您可以确定应该使用哪个库的情况下。如果您没有在两个库中进行链接(或者它们的名称空间冲突禁止链接)那么这就行不通了。#define/#ifdef并不总是友好的,但有时它是最好的解决方案。要添加到mah,如果使用包装器Foo,只需声明任何必须重写为纯虚拟的函数。一旦您尝试实例化具体子类,编译器将强制您在具体子类中提供实现。ex这正是我的意图,但我无法安装Foo,因为它是abstract类。我是否遗漏了什么?好吧,听起来你想为抽象库提供一个工厂,以选择在运行时动态提供哪个Foo实现?@mah,没有名称空间冲突,我可以链接两个库。我需要实例化Foo Thought,但你仍然需要有一个地方,让您决定是使用
    FooX1
    还是
    FooX2
    实例化模板-这会带回#ifdef或类似的东西。使用模板的想法很好,though@Sergey我花了一些时间思考发生了什么,但这就是我要做的
    Foo* MakeFoo();
    
    template<typename FooX>
    class FooVariant1
    {
    public:
        FooVariant1()
        {
            impl=new FooX();
        }
    
        void Met1Wrapper()
        {
            impl->Met1();
        }
    private:
    
        FooX *impl;
    };
    
    FooVariant1<FooX1> bar;
    bar.Met1Wrapper();
    
    template<typename FooX>
    class FooVariant2 : public FooX
    {
    };
    
    FooVariant2<FooX1> bar;
    bar.Met1();