itkMacro.h —— ITK宏详细解析

来源:互联网 发布:淘宝卖家服务热线 编辑:程序博客网 时间:2024/05/01 23:12
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;
    /** Method for creation through the object factory. */
itkNewMacro(Self);

再来看一下itkTypeMacro(thisClass,superclass)这个宏,其展开后是:
/** Macro used to add standard methods to all classes, mainly type
* information. */
#define itkTypeMacro(thisClass,superclass) \
virtual const char *GetNameOfClass() const \
{return #thisClass;}

ITK的解释已经很清楚了,就是添加标准方法到所有的类当中,还有运行时类型识别等相关信息。这个宏也是书写ITK类时必须包含的宏之一。
例如 (还是itk::MattesImageToImageMetric里面的代码):
  /** Run-time type information (and related methods). */
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);

暂时先写这么多。
原创粉丝点击