Options for class design using safe downcasting

前端 未结 3 1893
佛祖请我去吃肉
佛祖请我去吃肉 2021-01-16 07:31

Hi I\'ve started working on some pre-existing code which consists of a tree of elements, each element is a descendant of a generic element which has a type data member.

相关标签:
3条回答
  • 2021-01-16 07:57

    dynamic_cast is not that slow, and you're likely not going to be able to do better. Profile and prove that it is a performance bottleneck before looking at alternative solutions. Never ever do anything because you maybe heard somewhere that it might be slow.

    0 讨论(0)
  • 2021-01-16 07:58

    Let the base class in the tree structure have a pure virtual Visit() method.

    class CBase {
      virtual void Visit(CVisitor* visitor) const = 0;
    };
    

    Let the inherited classes implement it:

    class CFoo : public CBase {
      virtual void Visit(CVisitor* visitor) const {
        visitor->Accept(this);
      }
    };
    
    class CBar : public CBase {
      virtual void Visit(CVisitor* visitor) const {
        visitor->Accept(this);
      }
    };
    

    The final magic:

    class CVisitor {
      void Accept(CFoo* foo) {
        // operate on CFoo*
      }
      void Accept(CBar* bar) {
        // operate on CBar*
      }
    };
    

    So all you need to do is to create Accept and Visit methods for new types and traverse the tree with the CVisitor class and then you can operate on any type in the tree without any pointer casts.

    Hope this helps.

    Cheers

    0 讨论(0)
  • 2021-01-16 08:06

    If dynamic_cast/RTTI is not an option, an easy way of dealing with this type of situation is by use of the Visitor Pattern

    Basically, you define a base class that defines methods that do the casting for you safely:

        // Forward declarations.
    class CFoo;
    class CBar;
    
    class CommonBase
    {
    public:
        virtual CFoo* GetFoo( void ) { return NULL };
        virtual CBar* GetBar( void ) { return NULL };
    };
    
    class CFoo : public GenericBase, public CommonBase
    {
        .
        .
    public:
        CFoo* GetFoo( void ) { return this };
    };
    
    class CBar : public GenericBase, public CommonBase
    {
        .
        .
    public:
        CBar * GetBar( void ) { return this };
    };
    

    Now, given a pointer to a CommonBase object one can downcast by "visting":

    CommonBase *p;
    CFoo pFoo = p->GetFoo();
    if( pFoo )
    {
        // Winner!
    }
    
    0 讨论(0)
提交回复
热议问题