Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.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++中的循环依赖问题。< /P>_C++_Templates_Circular Dependency_Extensible - Fatal编程技术网

C++;使用类模板的循环依赖-如何重构? 我处理C++中的循环依赖问题。< /P>

C++;使用类模板的循环依赖-如何重构? 我处理C++中的循环依赖问题。< /P>,c++,templates,circular-dependency,extensible,C++,Templates,Circular Dependency,Extensible,情况如下: libA.so: - Body.cpp - Header.cpp - DataObject.cpp - DataObject::read(boost::asio::streambuf* data) { boost::asio::streambuf data; .... body = (new DataConverter<Body>)->convert(&

情况如下:

libA.so:
    - Body.cpp
    - Header.cpp
    - DataObject.cpp
    - DataObject::read(boost::asio::streambuf* data)
      {
          boost::asio::streambuf data;

          ....

          body = (new DataConverter<Body>)->convert(&data);
          header = (new DataConverter<Header>)->convert(&data);
      }

  libB.so:
      - DataConverter.cpp
          -> DataConverter<T>
          -> T* DataConverter<T>::convert(boost::asio::streambuf* data)

  libA.so <-> libB.so
libA.so:
-Body.cpp
-Header.cpp
-DataObject.cpp
-数据对象::读取(boost::asio::streambuf*数据)
{
boost::asio::streambuf数据;
....
body=(新数据转换器)->convert(&data);
header=(新数据转换器)->convert(&data);
}
libB.so:
-DataConverter.cpp
->数据转换器
->T*DataConverter::convert(boost::asio::streambuf*数据)
libA.so libB.so
存在循环依赖关系,因为libA使用libB中的Converter类,libB现在需要了解需要转换的libA的对象类型,因为DataConverter::convert返回一个Body或Header对象

我曾想过用前瞻性声明来解决这个问题,但对我来说,这似乎不是最干净的解决方案。总之,我的计划是提供一个可扩展的DataConverter解决方案

你们认为什么是最佳实践?也欢迎完全不同的设计:)

最好的,
Sebastian

您可能希望创建定义接口的抽象基类,并隐藏彼此之间的实现(派生类)。

如果您需要类模板
DataConverter
,则这不能是任何编译库的一部分。它必须通过包含文件提供。一旦您将
DataConverter
代码放入一个标头中,供
libA
libB
使用,您的循环依赖性就会消失。

您的设计似乎有缺陷。如果名为A和B的两个库相互依赖,则意味着它们必须始终一起装运。如果它们必须始终一起装运,这意味着它们在逻辑上是同一接口的一部分。这意味着事实上,你只有一个图书馆

没有足够的信息说明什么是最佳解决方案,但以下是一些提示:

  • 合并这些库
  • 例如,通过将DataConverter移动到libA,使一个库依赖于另一个库
  • 创建一个实用程序库,依赖于这两个工具库
  • 使用模板或虚拟类在libB中创建适当的接口,并使libA依赖于libB。后者(虚拟类)很可能是动态链接库中更好的选择
  • 一些备选方案:

  • DataConverter
    作为一个完全通用的实现,将在编译时使用适当的类型在libA.so中实例化。这是一个典型的c++-ish解决方案。来自libA(或其他)的“可转换”类型必须满足一些
    convertable
    概念,
    DataConverter
    的完全模板化实现将使用这些概念

  • JohnB提出的依赖倒置。您基本上可以实现相同的目标,但需要在运行时使用接口、实现和注册/解析。还有很多工作要做,但可扩展、ABI可实现、可部署为库等

  • 两者的某种巧妙结合,比如
    Boost.Serialization
    。然而,这很难实现,也很容易打破


  • 好的-如何定义一个AbstractConverter工厂,它实际返回指定模板化目标格式的具体实现。但这将如何解决我的依赖性问题呢?定义一个包含转换器所需的所有方法(抽象)的抽象类。您可以在头文件中执行此操作。在liba.so和libb.so的源中包括此标头。libb中的转换器(实际上,很可能)派生自抽象类。libb包含两个返回转换器的工厂方法,这些工厂方法在liba中声明为extern。因此,libb知道liba,但liba现在不知道libb。这看起来像是内存泄漏——你几乎肯定想要
    DataConverter().convert(&data)
    ,没有
    new
    (除非
    convert
    delete this
    结尾,但那会很可怕)。这是比其他任何东西都更伪的代码:)