【问题标题】:Derived class dependent function派生类依赖函数
【发布时间】:2015-07-07 18:19:54
【问题描述】:

我有基类DataProcessor。它是某些坐标系中位置计算器的基类。因此,例如,它可以有如下后代:SphericDataProcessorCartesianDataProcessor。有一个基类CookedDataCatalogue,它是一些对象位置容器的基类。所以每个DataProcessor 都应该能够将其数据放到每个CookedDataCatalogue 中。我可以想象这样的事情:

class CookedDataCatalogue
{
    virtual void Transform(DataProcessor* dp) = 0;

    virtual void PutData(???) = 0;
}


class CookedDataCatalogue1 : public CookedDataCatalogue
{
    void Transform(DataProcessor* dp) override
    {
        dp->TransformTo(this);
    }
}

class CookedDataCatalogue2 : public CookedDataCatalogue
{
    ...
}

class CookedDataCatalogue3 ...

class DataProcessor
{
    virtual void Process() = 0;

    virtual void TransformTo(CookedDataCatalogue1* c) = 0;
    virtual void TransformTo(CookedDataCatalogue2* c) = 0;
    virtual void TransformTo(CookedDataCatalogue3* c) = 0;
}

但我不喜欢它。首先void Transform(DataProcessor*) 从基类迁移到所有子类**。其次,如果我将它构建为库,其他用户无法添加自己的CookedDataUserCatalogue,因为他无法添加另一个void TransformTo(CookedDataUserCatalogue)。第三,我不知道函数PutData()怎么写,因为每个Catalog都用自己的数据来包含。是否应该模板化?

什么是解决方案?有没有我错过的编程模式?

【问题讨论】:

  • 在网上搜索“double dispatch pattern c++”。
  • 我理解错了吗:煮熟的不是多余的吗!?你只需要一个DataProcessorInterface
  • 目录可以由其他人提供,DataProcessor 不仅可以放入数据,还可以在其中搜索。

标签: c++ class oop design-patterns


【解决方案1】:

有两种方法可以做到这一点以及 cmets 中提到的双重调度模式:

基线

首先是您指定一组“基线”坐标。为了转换,您首先转换为核心集,然后再从其转换。

优点:你只需要为任意数量的不同DataProcessors写一个toBaselinefromBaseline。添加新的DataProcessor 就像创建它然后将转换写入核心集和从核心集写入一样简单。

缺点:在大多数情况下,当您进行两次转换时,性能会受到影响。由于表示或转换方面的损失,准确性可能会受到影响。

变压器对象

创建一个接口,将对象从DataProcessor 转换为DataProcessor

为每个支持的转换创建该接口的实例。

有一个实用程序类,其中包含要使用的正确转换的源和目标对映射。调用该实用程序类的方法以按需执行转换。

优点:无需进行多次转换而造成浪费。

缺点:需要创建 n^2 个 Transform 对象,其中 n 是不同 DataProcessor 对象的数量。创建新的DataProcessor 时,您需要为每个添加的DataProcessor 编写和添加Transform 对象。缺少Transforms 将在运行时而不是编译时检测到。

【讨论】:

    猜你喜欢
    • 2018-05-02
    • 1970-01-01
    • 1970-01-01
    • 2013-09-13
    • 2011-01-06
    • 2020-01-20
    • 1970-01-01
    • 1970-01-01
    • 2012-03-08
    相关资源
    最近更新 更多