天天看点

itkMacro.h —— ITK宏详细解析

ITK的源代码使用了相当多的宏。查看帮助文档和类的头文件时,会发现帮助文档里的好多函数在头文件里找不到明显的定义,比如说好多函数都是以”Set”或”Get”打头的,但是头文件就是找不到有Set***的函数定义,这就是宏的作用,下面来详细地探讨一下ITK里的宏定义。

ITK几乎所有的宏都集中在itkMacro.h文件里,下面结合例子对这里面的常见的宏作一个解析。

首先来看一下itkNewMacro(x),这个宏展开就是:

#define itkNewMacro(x) \

static Pointer New(void) \

{ \

  Pointer smartPtr = ::itk::ObjectFactory<x>::Create(); \

  if(smartPtr.GetPointer() == NULL) \

    { \

    smartPtr = new x; \

    } \

  smartPtr->UnRegister(); \

  return smartPtr; \

} \

virtual ::itk::LightObject::Pointer CreateAnother(void) const \

{ \

  ::itk::LightObject::Pointer smartPtr; \

  smartPtr = x::New().GetPointer(); \

  return smartPtr; \

}

这个宏的作用是提供两种方法创建对象,第一种方法是New(),它是从类工厂(class factory)里返回指向x对象的指针;第二种方法是从一个实例当中创建对象。这是ITK提供的创建对象的一种机制,当创建对象时,ITK首先会去class factory里找和x同名的类,如果存在这个类,就返回指向这个对象的指针;如果找不到,就用标准的C++方法new一个。在ITK里要写自己的类或从ITK里的类派生出别的类时,都要用这个宏来创建对象。因为在ITK里构造函数是无法调用的,构造函数在ITK里都受保护类型。

比如说itk::MattesImageToImageMetric这个类的头文件里,就有下面这几句代码:

public:

typedef MattesMutualInformationImageToImageMetric  Self;

itkNewMacro(Self);

再来看一下itkTypeMacro(thisClass,superclass)这个宏,其展开后是:

#define itkTypeMacro(thisClass,superclass) \

virtual const char *GetNameOfClass() const \

{return #thisClass;}

ITK的解释已经很清楚了,就是添加标准方法到所有的类当中,还有运行时类型识别等相关信息。这个宏也是书写ITK类时必须包含的宏之一。

例如 (还是itk::MattesImageToImageMetric里面的代码):

itkTypeMacro(MattesMutualInformationImageToImageMetric, ImageToImageMetric);

第三个宏:itkStaticConstMacro(name,type,value),这个宏展开后比较容易:

#define itkStaticConstMacro(name,type,value) \

static const type name = value

就是把value的值赋给name,name的类型是static const type。

如:

  itkStaticConstMacro( MovingImageDimension, unsigned int,

                       MovingImageType::ImageDimension );

第四个宏:itkSetClampMacro(name,type,min,max).这个宏的作用就是设置name的取值范围,类型是type。而且创建”Set##name()”成员函数。原来“Set**()”这一类成员函数是这么来的。这只是其中创建这类成员函数的宏之一。如下面的例子:

  itkSetClampMacro( NumberOfSpatialSamples, unsigned long,

                    1, NumericTraits<unsigned long>::max() );

它的作用就是使NumberOfSpatialSamples的值在1和NumericTraits<unsigned long>::max()之间,而且创建成员函数SetNumberOfSpatialSamples()成员函数。难怪我们在itk::MattesImageToImageMetric.h里找不到SetNumberOfSpatialSamples()这个函数的定义,但是类itk::MattesImageToImageMetric却有这个函数的说明,原来是这么来的。

第五个宏:itkGetConstReferenceMacro(name,type),展开它:

#define itkGetConstReferenceMacro(name,type) \

  virtual const type & Get##name () const \

  { \

    itkDebugMacro("returning " << #name " of " << this->m_##name ); \

    return this->m_##name; \

}

作用是什么呢?很明显,创建了成员函数“Get##name()”,返回值是m_##name的一个常引用。 看一个例子就更清楚了:

itkGetConstReferenceMacro( NumberOfHistogramBins, unsigned long);

就是创建了成员函数:GetNumberOfHistogramBins(),这个成员函数的作用当然就是返回m_NumberOfHistogramBins这个数据成员变量的值,它的值是一个常量。

第六个宏:itkSetMacro(name,type).它的作用有点类似于itkSetClampMacro

就差个Clame了,也就是没有取值范围这个限制,那么它的作用就是创建成员函数”Set##name()”,展开它就是:

#define itkSetMacro(name,type) \

  virtual void Set##name (const type _arg) \

  { \

    itkDebugMacro("setting " #name " to " << _arg); \

    if (this->m_##name != _arg) \

      { \

      this->m_##name = _arg; \

      this->Modified(); \

      } \

}

看一个例子吧:

itkSetMacro(UseAllPixels,bool);

也就是创建”SetUseAllPixels(const bool _arg)”这个成员函数。

与上面相关的宏就是: itkBooleanMacro(name),展开就是:

#define itkBooleanMacro(name) \

  virtual void name##On () { this->Set##name(true);} \

virtual void name##Off () { this->Set##name(false);}

很明显,就是创建两个成员函数:name##On(),它的值就是Set##name(true);name##Off(),它的值是Set##name(flase)。

这个宏itkBooleanMacro都会和itkSetMacro联用的,以提供设置开关参数另外一种方法。看下面一个例子:

itkBooleanMacro(UseAllPixels);

暂时先写这么多。