template inheritance

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • morphique
    New Member
    • Feb 2010
    • 5

    template inheritance

    how can I get this upcasting to work:

    Code:
    template <class T>
    class BP : public T
    {}
    ;
    class DD : public class ST
    {}
    ;
    class ST
    {};
    
    int main(int argc, char** argv)
    {
    shared_ptr<BP<ST> > spST;
    shared_ptr<BP<DD> > spDD(new BP<DD>());
    spST = boost::dynamic_pointer_cast<BP<ST> >(spDD); <-----------this line throws assertion px!=0 failed
    }
    is it something acheivable? i have just posted the design otherwise classes contains all the constructor, members etc.
    Last edited by Banfa; Mar 1 '10, 09:29 AM. Reason: Added code tags
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    class DD : public class ST
    {}
    ;
    class ST
    {};
    This violates a prome rule of inheritance: Never derive from concrete classes.
    (See Scott Meyer More Effective C++ pp 258-270).

    You need DD to derive from an ABC aand ST to derive from the same ABC.

    That way you create a DD or an ST but use it as an ABC*.

    In your example you create a DD and the address of this object cannot ever be a pointer to an ST becuse it is not an ST.

    Remember, when you cast in C++ is because a) you care calling some relic function with a void* or somesuch or b) your C++ design is screwed up.

    Comment

    • morphique
      New Member
      • Feb 2010
      • 5

      #3
      it's not casting from DD to ST which is a problem as that works. ST contains virtual methods. It's a casting from BP<DD> to BP<ST> which throws runtime exception.

      Comment

      • weaknessforcats
        Recognized Expert Expert
        • Mar 2007
        • 9214

        #4
        It's probably that the dynamic_cast makes a run-time check to verify that the object at the address you are casting from is, in fact, an object of the type you are casting to AND that the type you are casting from and casting to are in the same inheritance hierarchy.

        What you have are BP objects and BP is not part of an inheritance hierarchy. Instead, these are handle objects that manage DD and ST objects. I expcect you will need an operator DD and an operator ST to support your cast. And then, you won't use a dynamic_cast but use a normal cast instead.

        It still begs the question why you are doing this. Problems like this are usually handled by creating a Factory class that returns the adress of the correct type of object. The Factory object is created inside a Create function that returns the adress returned by the Factory. This is a common design pattern.

        Comment

        • morphique
          New Member
          • Feb 2010
          • 5

          #5
          Code:
          if ((*pmapVarNameAndValues)["type"] == "stddeviation")
               {
                   shared_ptr<BP<StdDeviations> > pBP(new BP<StdDeviations>());
                   SHlpr::ConfigureStdDeviationsFromVariables(boost::dynamic_pointer_cast<StdDeviations>(pBP), *pmapVarNameAndValues);
                   pBP->m_itStartTime = iStartTimeOffset;
                   for(int i = 0; i < iRows - 1; i++)
                   {
                       for(int j = 0; j < 6; j++) dpocv[j] = npyary[i][j];
                       pBP->OnUpdate(dpocv);
                   }
                  pBP->m_bEnabled = false;
                   for(int j = 0; j < 6; j++) dpocv[j] = npyary[iRows - 1][j];
                   pBP->OnUpdate(dpocv);
                   pBP->Log(vctLog);
          
               }
               else if ((*pmapVarNameAndValues)["type"] == "stddeviationrev")
               {
                   shared_ptr<BP<StdDeviationsRev> > pBP(new BP<StdDeviationsRev>());
                   SHlpr::ConfigureStdDeviationsFromVariables(boost::dynamic_pointer_cast<StdDeviations>(pBP), *pmapVarNameAndValues);
                   pBP->m_itStartTime = iStartTimeOffset;
                   for(int i = 0; i < iRows - 1; i++)
                   {
                       for(int j = 0; j < 6; j++) dpocv[j] = npyary[i][j];
                       pBP->OnUpdate(dpocv);
                   }
                   pBP->m_bEnabled = false;
                   for(int j = 0; j < 6; j++) dpocv[j] = npyary[iRows - 1][j];
                   pBP->OnUpdate(dpocv);
                   pBP->Log(vctLog);
          
               }
               else if ((*pmapVarNameAndValues)["type"] == "smoregression")
               {
                   shared_ptr<BP<SmoRegression> > pBP(new BP<SmoRegression>());
                   SHlpr::ConfigureSmoRegressionFromVariables(boost::dynamic_pointer_cast<SmoRegression>(pBP), *pmapVarNameAndValues);
                   pBP->m_itStartTime = iStartTimeOffset;
                   for(int i = 0; i < iRows - 1; i++)
                   {
                       for(int j = 0; j < 6; j++) dpocv[j] = npyary[i][j];
                       pBP->OnUpdate(dpocv);
                   }
                   pBP->m_bEnabled = false;
                   for(int j = 0; j < 6; j++) dpocv[j] = npyary[iRows - 1][j];
                   pBP->OnUpdate(dpocv);
                   pBP->Log(vctLog);
          
               }
               else if ((*pmapVarNameAndValues)["type"] == "detrendeddev")
               {
                   shared_ptr<BP<DetrendedDev> > pBP(new BP<DetrendedDev>());
                   SHlpr::ConfigureDetrendedDevFromVariables(boost::dynamic_pointer_cast<DetrendedDev>(pBP), *pmapVarNameAndValues);
                   pBP->m_itStartTime = iStartTimeOffset;
                   for(int i = 0; i < iRows - 1; i++)
                   {
                       for(int j = 0; j < 6; j++) dpocv[j] = npyary[i][j];
                       pBP->OnUpdate(dpocv);
                   }
                   pBP->m_bEnabled = false;
                   for(int j = 0; j < 6; j++) dpocv[j] = npyary[iRows - 1][j];
                   pBP->OnUpdate(dpocv);
                   pBP->Log(vctLog);
          
           }
          I just want to generalize code below instead of calling it in every else if. All the template argument class to BP are derived from ST. OnUpdate is a vistual method. m_bEnabled is a memeber of ST. So this should work just need to figure out the way to cast BP<DerivedClass > to BP<ST>
          for(int i = 0; i < iRows - 1; i++)
          99 {
          100 for(int j = 0; j < 6; j++) dpocv[j] = npyary[i][j];
          101 pBP->OnUpdate(dpocv );
          102 }
          103 pBP->m_bEnabled = false;
          105 for(int j = 0; j < 6; j++) dpocv[j] = npyary[iRows - 1][j];
          106 pBP->OnUpdate(dpocv );
          107 pBP->Log(vctLog);

          Comment

          • weaknessforcats
            Recognized Expert Expert
            • Mar 2007
            • 9214

            #6
            I am still not with you.

            DD is your base class. ST is your derived class.

            You create ST objects and use them through DD pointers. There is no cast. and ST IS-A DD.

            DD* ptr = new ST;

            Your shared_ptr would be managing a DD*.

            There will be no ST pointers in your code.

            Comment

            • morphique
              New Member
              • Feb 2010
              • 5

              #7
              DD is derived class and ST is base class. that all works fine. The issue is with BP which derives from template class argument.

              So instead of creating
              BP1 from DD1
              BP2 from DD2
              BP3 from DD3
              i have created
              template<class T>
              BP : public <T>

              DD1, DD2, DD3 and so on all derives from ST
              so I just want to cast BP<DD1>, BP<DD2> so on to BP<ST>

              Comment

              • Banfa
                Recognized Expert Expert
                • Feb 2006
                • 9067

                #8
                You have not understood your own inheritance tree. You should draw it out, something that is normally worth while on any progrect if you have actually created your inheritance tree during the design stage before you started programming. If you did you would find it looked something like

                Code:
                                   ST
                                    |
                  ---------------------------------------
                  |           |            |            |
                BP<ST>       DD1          DD2          DD3
                              |            |            |
                           BP<DD1>      BP<DD2>      BP<DD3>
                From this it is easy to see that you can cast BP<DD1> to BP<ST> because they are on different branches of the inheritance tree.

                A BP<DD1> is a DD1 and it is an ST but it is not a BP<ST>.

                Comment

                • morphique
                  New Member
                  • Feb 2010
                  • 5

                  #9
                  yes that's what causing issues. is there any way I can execute ST virtual functions on BP<DD> which i doubt. any design pattern recommend which best fits this scenario. I am willing to make design changes unless they are drastic.

                  Thanks for you time I really appreciate that.

                  Comment

                  • weaknessforcats
                    Recognized Expert Expert
                    • Mar 2007
                    • 9214

                    #10
                    This is looking like you need a Handle. Read this: http://bytes.com/topic/c/insights/65...-smart-pointer

                    There still should not be a need for a cast:

                    Code:
                    class ST
                    {
                    public:
                    	virtual void Hello()  {cout << "Hello" << endl;}
                    
                    };
                    class DD : public ST
                    {
                    
                    };
                    
                    
                    class BP
                    {
                         ST* theObject;
                    public: 
                    	BP(ST* obj) : theObject(obj) {};
                    	ST* operator->() {return theObject;}
                    };
                    
                    int main()
                    {
                    	ST* obj = new DD;
                    	BP handle(obj);
                    	handle->Hello();
                    
                    }
                    Here BP is a handle object. The insight article covers this in detail.

                    Comment

                    Working...