由于C ++语言限制,我的实际想法不是编译(不支持模板化虚函数)。也许你们中的一些人对以下代码片段有一些设计建议。
我想在不同类型的输入上运行不同的算法。例如,我输入了积分图像和灰度图像。对于像素,积分图像需要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
)都是模板化的,这是我不想做的事情。我在这里看到了一些帖子,建议使用访问者模式。但说实话,我不知道如何在我的情况下使用它。
答案 0 :(得分:0)
不确定这是否能解决您的所有问题,因为您实际上希望这些代码实际上“做”的内容并不多,但只需稍微改组,它就会编译:
typedef float float32_t;
class CChannelBase
{
public:
virtual ~CChannelBase( void ) = 0;
};
template <class ValueType>
class CChannel : public CChannelBase
{
public:
typedef ValueType value_type_t;
CChannel(): 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;
};
template <class ValueType>
class IAlgorithmInterface
{
public:
virtual ~IAlgorithmInterface() = 0;
virtual void doWork(const CChannel<ValueType>* f_channel_p, float32_t& f_result_r);
};
template <class ValueType>
class CAlgorithmA : IAlgorithmInterface<ValueType>
{
CAlgorithmA() {};
~CAlgorithmA() {};
void doWork(const CChannel<ValueType>* f_channel_p, float32_t& f_result_r) {};
};
template <class ValueType>
class CAlgorithmB : IAlgorithmInterface<ValueType>
{
CAlgorithmB() {};
~CAlgorithmB() {};
void doWork(const CChannel<ValueType>* f_channel_p, float32_t& f_result_r) {};
};
int main()
{
}
实质上,只需移动templace<class ValueType> out a level, to the class, and add it to the
IAloorithmInferface`继承。
我完全希望被告知这对你要做的事情不起作用,但是没有你想要这些课程做什么的例子,所以我无法确定它是否有效。
答案 1 :(得分:0)
好的,这有点令人费解,但你有一种复杂的要求。 IAlgorithmInterface
可以有模板方法,但不能是虚拟方法。您可以创建一个中间类,它本身是一个虚拟派生自IAlgorithmInterface
的模板,它将模板方法代理到执行实际工作的某些代码。实际工作在模板参数中提供,该模板参数用于IAlgorithmInterface
的模板推导。
此方案允许IAlgorithmInterface
的模板方法通过向下转发分派到适当的派生类。
class IAlgorithmInterface
{
public:
virtual ~IAlgorithmInterface() {}
template <class ValueType>
void doWork(const CChannel<ValueType>* f_channel_p, float32_t& f_result_r);
};
template <class ValueType, typename RealWork>
class IAlgorithmTemplate : virtual public IAlgorithmInterface
{
public:
void doWork(const CChannel<ValueType>* f_channel_p, float32_t& f_result_r) {
RealWork()(f_channel_p, f_result_r);
}
};
template <class ValueType>
void IAlgorithmInterface::doWork(const CChannel<ValueType>* f_channel_p,
float32_t& f_result_r)
{
IAlgorithmTemplate<ValueType> *alg
= dynamic_cast<IAlgorithmTemplate<ValueType>*>(this);
alg->doWork(f_channel_p, f_result_r);
}
现在,通过多重继承,我们可以创建算法实现将使用的实际接口。由于IAlgorithmTemplate
使用虚拟继承,因此只有一个IAlgorithmInterface
实例。因此,要支持ValueTypeNew
,您需要在继承列表中添加IAlgorithmTempalte<ValueTypeNew>
。
template <template <class> class RealWork>
class IAlgorithmBase :
public IAlgorithmTemplate<ValueTypeOne, RealWork<ValueTypeOne> >,
public IAlgorithmTemplate<ValueTypeTwo, RealWork<ValueTypeTwo> >,
//...
public IAlgorithmTemplate<ValueTypeLast, RealWork<ValueTypeLast> > {
};
最后,每个算法都派生自IAlgorithmBase
,并将RealWork
作为模板实现。
template <class ValueType>
struct RealAlgorithmA {
void operator () (const CChannel<ValueType>* f_channel_p, float32_t& f_result_r) {
//...
}
};
class CAlgorithmA : public IAlgorithmBase<RealAlgorithmA>
{
public:
CAlgorithmA() {...}
~CAlgorithmA() {...}
};