[Insight-users] Problems with Templates and Inheritance

Luis Ibanez luis.ibanez at kitware.com
Sat Jun 12 11:43:49 EDT 2004


Hi Michael,

There are several ways of passing image information
without exposing the templated aspect of the image class.


Here are two options:

1) Use the grand-parent class of the Image, the: DataObject
    as the pointer to be passed to your function, and define
    a set of "enums" for each possible expected image type.

    e.g.  enum { charImage, intImage, floatImage } myTypes

    The signature for your function will then be:

    Send( const itk::DataObject * image, myTypes type );

    Internally, in the Send method you will be able to
    downcast the DatObject pointer to its true nature,
    using a switch statement

    Send( const itk::DataObject * data, myTypes type )
      {
      switch(type)
      {
      case charImage:
         {
         typedef itk::Image< char, 3 >  charImageType;
         charImageType::ConstPointer image =
               static_cast< const charImageType * >( data );
         ///... use the image....
         break;
         }
      case intImage:
         {
         typedef itk::Image< int, 3 >  intImageType;
         intImageType::ConstPointer image =
               static_cast< const intImageType * >( data );
         ///... use the image....
         break;
         }
      case .... etc

      }
    }


   Note that this heavily rely on your consistency for
   passing the correct enum value to the function. Very
   bad things will happen if you send the wrong enum
   value...   :-/



2) A second option is to rely on the Run-Time Type Information
    system (RTTI), which allows you to attempt down_casting the
    data pointer to any of the expected image types and see which
    one succeds. In that case, you simply attempt all the conversion
    like in:

    Send( const itk::DataObject * image)
     {
     typedef itk::Image< char, 3 >    charImageType;
     typedef itk::Image< int, 3 >     intImageType;
     typedef itk::Image< float, 3 >   floatImageType;

     const charImageType  * image1 = NULL;
     const intImageType   * image2 = NULL;
     const floatImageType * image3 = NULL;

     try
       {
       image1 = dynamic_cast< const charImageType * >( data );
       }
     catch(...)
       {
       try
          {
          image2 = dynamic_cast< const intImageType * >( data );
          }
       catch(...)
          {
          try
            {
            image3 = dynamic_cast< const floatImageType * >( data );
            }
         catch(...)
            {
            std::cerr << "Image Type unknown " << std::endl;
            return 1;
            }
          }
       }

     // At this point only of of the three pointers: image1,
     image2, image3 should be different from NULL, and that's
     the pointer with the real image type that was passed.


Note that you still need to inform the received about the
image type that you are passing.



Regards,



    Luis



------------------
Michael wrote:

>  Hi,
> 
> I would like create an abstract communication class (let's call it 
> Communicator), which provides an interface consisting of some point to 
> point communication methods. It should then be possible to derive 
> different specialized Communicator classes from this abstract class (for 
> example SocketCommunicator, MPICommunicator, ...). Among the point to 
> point communication methods, I'd like to have a method for sending 
> (ITK-) image data. Something like:
> 
> Send(const ImageType* image, ...)
> 
> Since itkImage is a templated class, I have to use templates to define 
> the parameter image. I don't want to use templates at class level, i.e.
> 
> template <class ImageType>
> class Communicator {
> ...
> }
> 
> , for two reasons:
> 
> 1) the communicator should be usable in enviorenments where no images 
> have to be sent (and where they don't even exist)
> 2) one single instance of the communicator may have to send different 
> images (of different types). I don't want to list all of them as 
> templates (template<class ImageType1, class ImageType2, .., class 
> ImageTypeN.>), even though the number of N is known for my particular 
> application, since it might be different when the same communicator 
> class should be reused in another environment.
> 
> Usually (i.e. with non templated parameters), I would just define a send 
> method in the abstract communicator class which uses the image 
> superclass (let's call it ImageSuperclass) as a parameter:
> 
> virtual void Send(ImageSuperclass* image, ...) = 0;
> 
> This method could then send any derived image classes, say Short2DImage, 
> Char3DImage, ...
> 
> Then I would derive my specialized Communicator class, say 
> MPICommunicator, and this class would override the send method in the 
> abstract class. However, since the image class is templated, my method 
> has to look something like
> 
> template <class ImageType>
> void Send(ImageType* image, ...)
> 
> Unfortunately, templated member functions cannot be declared as virtual, 
> and can therefore not be overwritten by my derived MPICommunicator class.
> 
> Can anybody explain me how I can define an abstract communicator class 
> that defines a send method for the templated images and from which I can 
> derive different implementations of communicator classes 
> (MPICommunicator, SocketCommunicator, ...). The derived classes 
> obviously somehow have to reimplement the send method of the abstract 
> superclass.
> 
> Thanks,
> 
> Michael
> 
> _______________________________________________
> Insight-users mailing list
> Insight-users at itk.org
> http://www.itk.org/mailman/listinfo/insight-users
> 





More information about the Insight-users mailing list