Casting vtkSmartPointer to an Inherited Class

Viewed 536

How do I cast a vtkSmartPointer<T> to an inherited class while maintaining reference counting?

Minimal illustration:

#include <iostream>
#include <vtkSmartPointer.h>
class A: public vtkObjectBase {
public :
    A(){}
    static A * New(){return new A();}
    int var1 = 8;
};

class B: public A {
public :
    B(){}
    static B * New() {return new B();}
    int var2 = 12;
};

int main (int argc, char ** argv) {
    vtkSmartPointer<B> b = vtkSmartPointer<B>::New();
    vtkSmartPointer<A> a = b;  // this is fine
    std::cout << "var1 = " << a->var1 << std::endl;
    // this is not fine and I cannot find a vtk equivalent
    // to boost's dynamic_pointer_cast for similar functionality
//    vtkSmartPointer<B> c = a; // how do I do this?     
}

I'm assuming there must be a macro somewhere similar to boost's dynamic_pointer_cast<T> but I can't find it. If there isn't, and someone can suggest a method to accomplish this, I would be very grateful.

2 Answers

There are a couple of problems here.

  1. In most cases you want to inherit from vtkObject, not vtkObjectBase.
  2. You are missing vtkTypeMacro().
  3. What you are looking for is T::SafeDownCast().

So your code would become:

#include <vtkSmartPointer.h>

class A : public vtkObject {
public :
    vtkTypeMacro(A, vtkObject);

    A() = default;
    static A* New() { return new A(); }
    int var1 = 8;
};

class B : public A {
public:
    vtkTypeMacro(B, A);

    B() = default;
    static B* New() { return new B(); }
    int var2 = 12;
};

int main (int argc, char ** argv) {
    vtkSmartPointer<B> b = vtkSmartPointer<B>::New();
    vtkSmartPointer<A> a = b;
    vtkSmartPointer<B> c = B::SafeDownCast(a);
}

For more information, please, consult VTK User Guide, chapter "14.6 Writing A VTK Class".

Okay nevermind, I found an answer that appears to work. I'll post it in case someone stumbles across here and wants to avoid the frustration I had.

It turns out that reference counting happens in the vtkObjectBase. So as long as code inherits from that, vtk will keep an accurate count. Thankfully vtk won't let you use vtkSmartPointer unless it does.

So it would seem that to implement a boost style macro one could simply do the following:

template<typename T,typename V> vtkSmartPointer<T> vtkDynamicPointerCast(vtkSmartPointer<V> src) {
    T* v = dynamic_cast<T*>(src.Get());
    if (v) return vtkSmartPointer<T>(v);
    else return vtkSmartPointer<T>();
}
Related