Header-only vtk-derived class

#1

Hi,

I’m writing a few classes that derive from vtkSocketController. They have some things in common, so I’d like to write a small header-only abstract class for my other classes to inherit from. However, I’m having problems with vtkStandardNewMacro().

If I don’t call vtkStandardNewMacro(), then my_abstract_class::New() is undefined, as expected.

If I include vtkStandardNewMacro() in my_abstract_class.h, I get a “redefinition of ‘static my_abstract_class* my_abstract_class::New()’”, which is unexpected. This also happens if I try and manually expand the macro (and the macros it calls).

Are header-only vtk-derived classes possible? If so, what’s the recommended method for creating them?

Thanks,
Tom

(David Gobbi) #2

Hi Tom,

The abstract class should not declare a ::New() method. The only reason that some of VTK’s abstract classes have ::New() is so that they can use VTK’s factory mechanism. In general, VTK abstract classes do not have ::New().

Neither is it necessary to use vtkStandardNewMacro in your concrete classes. I’d still recommend it if your classes have a .cxx implementation, but if they are header-only like your abstract class, you can use this instead:

vtkMyClass *vtkMyClass::New()
{
  vtkMyClass *obj = new vtkMyClass;
#ifdef VTK_HAS_INITIALIZE_OBJECT_BASE
  obj->InitializeObjectBase();
#endif
  return obj;
}
1 Like
(David Gobbi) #3

One thing that I forgot in my last answer. In an abstract class, you must use vtkAbstractTypeMacro instead of vtkTypeMacro.

1 Like
#4

That’s done the trick, thanks David!

Is there any documentation anywhere on the vtk macro’s? This isn’t the first time I’d had problems with them, and a good reference would be really useful!

#5

Ah, sorry, this turned up after I’d posted my reply. It doesn’t seem to matter in my case whether I use the AbstractTypeMacro or the normal TypeMacro. The comments for AbstractTypeMacro are as follows:
// Allows definition of vtkObject API such that NewInstance may return a
// superclass of thisClass.

Edit: I’ve just realised my abstract class doesn’t include a pure virtual function, which I think explains why I don’t see errors when I use vtkTypeMacro.

(David Gobbi) #6

Part III of the old VTK User’s Guide had documentation on the macros, but it’s a bit out of date. I don’t know if there is a good online reference except for the vtkSetGet header itself and the class documentation for vtkObject.h and vtkObjectBase.h.

I just read through vtkSetGet.h again, and there are three macros with slightly different behavior. It also looks like vtkTypeMacro is currently preferred vs. vtkAbstractTypeMacro.

vtkTypeMacro - for concrete classes (and seemingly for abstract, too)
vtkAbstractTypeMacro - old macro for abstract classes
vtkBaseTypeMacro - for direct descendants of vtkObjectBase

The “slightly different behavior” is how they deal with NewInstance and NewInstanceInternal. I’d have to do further study to be certain of the implications. But it’s now apparent to me that the current practice is to use vtkTypeMacro even for abstract classes.

(David Gobbi) #7

@allison.vacanti do you know what the deal is with vtkAbstractTypeMacro? I distinctly remember it being added to VTK a few years ago, but it appears that it was never adopted for use by most developers. Only six classes use it:

Common/Core/vtkGenericDataArray.h
Common/Core/vtkMappedDataArray.h
Common/DataModel/vtkCellIterator.h
Common/DataModel/vtkUnstructuredGridBase.h
Filters/Points/vtkInterpolationKernel.h
Rendering/OpenGL2/vtkOpenGLGL2PSHelper.h
(Allison Vacanti) #8

vtkAbstractTypeMacro is identical to vtkTypeMacro, except that it doesn’t define NewInstanceInternal, since that calls thisClass::New() (which doesn’t exist for abstract classes).

(David Gobbi) #9

But thisclass::New() actually does exist as an inherited method (it must, since vtkObject defines it), and that is why vtkTypeMacro also works for abstract classes.

So I get the idea that vtkAbstractTypeMacro is preferred for abstract classes, but when it was introduced the existing VTK abstract classes were not modified to use it, so it only appears in recently added classes.

(Allison Vacanti) #10

Good point, it definitely doesn’t appear necessary. I had forgotten realized that vtkObject could be instantiated in my last comment.

I’m sure there was some reason it was added at the time, maybe to workaround a problematic compiler? I seem to recall having some issues with inherited static methods at some point… Whatever the reason, it could probably be removed/deprecated now.