【发布时间】:2013-08-27 21:56:25
【问题描述】:
由于 C++ 语言限制(不支持模板化的虚函数),我的实际想法没有编译。也许你们中的一些人对以下代码 sn-p 有一些设计建议。
我想对不同类型的输入运行不同的算法。例如,我有一个积分图像和一个灰度图像作为输入。积分图像需要 32 位像素,而我的灰度图像需要 8 位(仅作为示例)。因此,我有两个频道:CChannel<uint8> 和 CChannel<uint32>
因为我可以为单个图像有多个通道,所以我将通道存储在一个向量中,std::vector<CChannelBase*>...这就是 CChannelBase 类的理由。
class CChannelBase
{
public:
virtual ~CChannelBase( void ) = 0;
};
template <class ValueType>
class CChannel : public CChannelBase
{
public:
typedef ValueType value_type_t;
Channel(): m_data_p(0) {}
void setData(ValueType* f_data_p) { m_data_p = f_data_p; }
const ValueType getData( void ) { return m_data_p; }
private:
ValueType* m_data_p;
};
我所有的算法都实现了一个接口,并且必须与每个图像通道兼容。
class IAlgorithmInterface
{
public:
virtual ~IAlgorithmInterface() = 0;
template <class ValueType>
virtual void doWork(const CChannel<ValueType>* f_channel_p, float32_t& f_result_r);
};
class CAlgorithmA : IAlgorithmInterface
{
CAlgorithmA() {...};
~CAlgorithmA() {...};
template <class ValueType>
void doWork(const CChannel<ValueType>* f_channel_p, float32_t& f_result_r) {...};
};
class CAlgorithmB : IAlgorithmInterface
{
CAlgorithmB() {...};
~CAlgorithmB() {...};
template <class ValueType>
void doWork(const CChannel<ValueType>* f_channel_p, float32_t& f_result_r) {...};
};
当然,这段代码没有被编译,因为我们有虚拟模板函数。无论如何,我正在寻找一个很好的设计来克服这个问题。一个解决方案是所有类(IAlgorithmInterface、CAlgorithmA、CAlgorithmB)都被模板化,这是我不想做的事情。我在这里看到了一些帖子,其中推荐了访问者模式。但老实说,我不知道如何在我的情况下使用它。
【问题讨论】:
-
将虚拟模板称为“缺少的语言功能”就像说您作为明星密码分析员的职业目前由于生活中缺少恒定时间素因数分解功能而被搁置。
-
你是说每个算法都需要能够处理多种不同的值类型,但它们总是以完全相同的方式处理?
-
是的,但是之前不知道图像数组的指针类型。当然,我可以重新解释给定的指针,但随后会出现问题。 @kerreksb:再次阅读我的文字:)
-
我们没有模板化的虚函数有一个很好的理由:它们没有意义。 virtual 表示“通过继承实现”,而 template 表示“继承实现”。您在这里真正想要的是特征和函子,例如 stl 使用。看看 STL 的分配器是如何工作的,这应该可以帮助您开始解决您以 C++ 方式描述的问题。
-
唯一可行的方法是写下 ValueType 的所有可能类型。 IE。让你的 doWork 函数接受一个变体
对象。这相当于编写了多个 doWork 重载(但也许变体的访问者会节省一些锅炉代码)
标签: c++ templates design-patterns virtual