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); 暂时先写这么多。 |
itkMacro.h —— ITK宏详细解析
最新推荐文章于 2023-02-09 17:41:52 发布