2010-11-20 38 views
4

我敢肯定答案是“你不能使用模板,你必须使用虚拟函数(动态多态)”,但它好像我必须复制大量的代码如果我走了那条路。这里是设置:“运行时间模板”

我目前有两个类,ColorImageSegmentation和GrayscaleImageSegmentation。他们做的事情本质上是一样的,但有三个不同点 - 它们在不同类型(ColorImage和GrayscaleImage)上运行 - 参数,直方图的维度(3 vs 1)不同 - PixelDifference函数根据图像类型

如果我创建一个类

template <TImageType> 
class ImageSegmentation 
{ 
}; 

我会在良好的状态。不过,我想有这样的对象作为另一个类的成员:

class MyMainClass 
{ 
ImageSegmentation MyImageSegmentation; 
}; 

但用户需要确定的MyImageSegmentation类型(如果用户打开一个灰度图像,我想要实例MyImageSegmentation<GrayScaleType>同样的。 。彩色图像,MyImageSegmentation<ColorType>

随着派生类,我可以存储一个指针,然后做:

class MyMainClass 
{ 
ImageSegmentation* MyImageSegmentation; 
}; 

... user does something... 
MyImageSegmentation = new ColorImageSegmentation; 

,但我怎么会做这样的事情有模板?问题是我有很多的:

typedef TImageType::HistogramType HistogramType; 
typedef TImageType::PixelType PixelType; 

样的东西怎么回事,所以我不知道我将如何将它们转换为动态多态模型,而不会复制一大堆的代码。

对不起漫不经心......有人对我有什么建议吗?

感谢,

大卫

+0

请编辑该问题以正确格式化代码示例。 – chris 2010-11-20 15:23:18

+0

Boost的GIL(http://www.boost.org/doc/libs/1_45_0/libs/gil/doc/index.html)也做同样的事情。你可以检查他们是如何解决这个问题的。 – liori 2010-11-20 17:36:00

回答

5

也许还有你还没有告诉我们关于额外的要求,但你有什么到目前为止,你可以通过包含类传下来的类型:

template<typename TImage> 
class MyMainClass 
{ 
    ImageSegmentation<TImage> MyImageSegmentation; 
}; 

最有可能你需要动态调度的某一层,但只在抽象的最高水平:

struct IMainClass 
{ 
    virtual bool SaveToFile(std::string filename) = 0; 
    virtual bool ApplySharpenFilter(int level) = 0; 
    ... 
}; 

template<typename TImage> 
class MyMainClass : public IMainClass 
{ 
    ImageSegmentation<TImage> MyImageSegmentation; 
public: 
    virtual bool SaveToFile(std::string filename); 
    virtual bool ApplySharpenFilter(int level); 
}; 

IMainClass* pMain = new MyMainClass<GrayscaleImage>(); 
+0

+1:制作一个通用的基类,然后用模板类从它派生出来。 – Puppy 2010-11-20 16:02:25

+0

即使让IMainClass拥有任何东西,还有什么意义?它可以是空的,然后真正的模板类可以从中派生出来。这仍允许 IMainClass * pMain = new MyMainClass (); 这正是我所期待的。对? – 2010-11-20 16:50:53

+0

它不“持有”任何东西。它是一个抽象的与图像类型无关的界面(或者任何控制图像)以跟踪当前图像。毕竟,您的“锐化”菜单项(如果这是一个photoshop克隆)必须影响活动文件,并且必须为无数种文件类型执行此操作。 – 2010-11-20 16:53:44

1

您想创建对象的模板化版本,但让这些对象根据模板化参数采用不同的参数类型?整合到图书馆中并不是一件容易的事,但有几种方法可以解决这个问题。

看看unary_function的灵感。在那里,他们正在使用模板化的特点,随身携带的类型参数,而无需运行任何类型的魔法:

template <class Arg, class Result> 
    struct unary_function { 
    typedef Arg argument_type; 
    typedef Result result_type; 
    }; 

“unary_function”不包含除声明typedef的其它任何功能。但是,这些类型定义允许您在代码中和编译时使用代码段之间的名称等价物来表示。他们利用模板参数的检查方式。

这意味着,你可以拥有这方面的工作对象:

template<typename T> 
struct Foo{ 
    typedef typename T::argument_type argument_type; 
    Foo(T _myFunc) : m_Func(_myFunc) 
    void myWrappedFunction(argument_type _argument){ m_Func(_argument); } 
}; 

内它包含的参数值类型,而无需事先指定它们。因此,如果您对每个图像对象都有pixel_type或类似的东西,则简单地指出typename T::pixel_type将调用您需要的类型参数。

+0

小麦,感谢您的回复。我不知道如何让T在运行时设置?事实上,我正在使用的库已经这样做了,我只需要在运行时指定T,这样T :: argument_type就是正确的类型。 – 2010-11-22 12:32:22