Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
CODE PROJECT For Those Who Code
  • Home
  • Articles
  • FAQ
Community
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Different methods in objects in a List

Different methods in objects in a List

Scheduled Pinned Locked Moved C / C++ / MFC
questionjsonhelptutorial
12 Posts 6 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P piul

    Hi there, I have a list in which each Node holds an object of the class CItem <pre></pre>

    class CList{
    ...
    CNode * mpListHead; };

    class CNode{
    double GetPos() const { return mpItem->GetPos(); }
    ...
    CItem * mpItem; };

    class CItem{
    double GetPos() const { return mdPosition; }
    ...
    double mdPosition; };

    Each Item can be of a different type

    class CEmboss : public CItem {...};
    class CAnneal : public CItem {...};

    And some of the items need to have some member data and functions that are not required in the rest, for example:

    class CEmboss : public CItem {
    ...
    int GetOrientation() const { return mnOrient; }
    ...
    int mnOrient; };

    The question is, how do I implement a GetOrientation() function in CNode?? I get a compiler error when mpItem->GetOrientation() because some of the Items don't have this method. One option is to put that function in CItem, even though it won't be used for some of the Items, but I'd prefer to put it only in CEmboss. Is there any way of doing this??

    C Offline
    C Offline
    Cedric Moonen
    wrote on last edited by
    #2

    You can cast your generic object into a CEmboss object. The best way to do it is to use dynamic_cast: CEmboss* pEmboss = dynamic_cast<CEmboss*>(pItem); if (pEmboss) pEmboss->GetOrientation(); The dynamic cast will return NULL if the object is not of the specified type (takes advantage of the run-time type information).

    Cédric Moonen Software developer
    Charting control [v1.3]

    1 Reply Last reply
    0
    • P piul

      Hi there, I have a list in which each Node holds an object of the class CItem <pre></pre>

      class CList{
      ...
      CNode * mpListHead; };

      class CNode{
      double GetPos() const { return mpItem->GetPos(); }
      ...
      CItem * mpItem; };

      class CItem{
      double GetPos() const { return mdPosition; }
      ...
      double mdPosition; };

      Each Item can be of a different type

      class CEmboss : public CItem {...};
      class CAnneal : public CItem {...};

      And some of the items need to have some member data and functions that are not required in the rest, for example:

      class CEmboss : public CItem {
      ...
      int GetOrientation() const { return mnOrient; }
      ...
      int mnOrient; };

      The question is, how do I implement a GetOrientation() function in CNode?? I get a compiler error when mpItem->GetOrientation() because some of the Items don't have this method. One option is to put that function in CItem, even though it won't be used for some of the Items, but I'd prefer to put it only in CEmboss. Is there any way of doing this??

      H Offline
      H Offline
      Hanan888
      wrote on last edited by
      #3

      Hi, How about that: in class CItem: virtual int GetOrientation() = 0 that makes CItem "uninstanceable" you cant have a CItem it's 'virtual class'. OR (I think it will better suit you) #define NO_ORIENTATION -1000 virtual int GetOrientation() {return NO_ORIENTATION;} in both ways: creating CEmboss and putting in the node (mpItem) then GetOrientation() will go to the GetOrientation() of CEmboss. This all stuff is called "polymorphism" in OOP.

      P 1 Reply Last reply
      0
      • H Hanan888

        Hi, How about that: in class CItem: virtual int GetOrientation() = 0 that makes CItem "uninstanceable" you cant have a CItem it's 'virtual class'. OR (I think it will better suit you) #define NO_ORIENTATION -1000 virtual int GetOrientation() {return NO_ORIENTATION;} in both ways: creating CEmboss and putting in the node (mpItem) then GetOrientation() will go to the GetOrientation() of CEmboss. This all stuff is called "polymorphism" in OOP.

        P Offline
        P Offline
        piul
        wrote on last edited by
        #4

        Thank you guys. I must admit that I don't like very much the option proposed by Hanan888, because I would end up having a lot of methods in CItem that are used only in some of its derived classes. It would make CItem a bit messy. On the other hand, I'd considered using dynamic casting, but the book I'm reading says it is not recommendable. That it might be a sign of poor inheritance hierarchy design. I was just wondering if there was any other way.

        B C H 3 Replies Last reply
        0
        • P piul

          Hi there, I have a list in which each Node holds an object of the class CItem <pre></pre>

          class CList{
          ...
          CNode * mpListHead; };

          class CNode{
          double GetPos() const { return mpItem->GetPos(); }
          ...
          CItem * mpItem; };

          class CItem{
          double GetPos() const { return mdPosition; }
          ...
          double mdPosition; };

          Each Item can be of a different type

          class CEmboss : public CItem {...};
          class CAnneal : public CItem {...};

          And some of the items need to have some member data and functions that are not required in the rest, for example:

          class CEmboss : public CItem {
          ...
          int GetOrientation() const { return mnOrient; }
          ...
          int mnOrient; };

          The question is, how do I implement a GetOrientation() function in CNode?? I get a compiler error when mpItem->GetOrientation() because some of the Items don't have this method. One option is to put that function in CItem, even though it won't be used for some of the Items, but I'd prefer to put it only in CEmboss. Is there any way of doing this??

          B Offline
          B Offline
          BadKarma
          wrote on last edited by
          #5

          Hi, you can use dynamic_cast to cast the CItem object to a class which does know the this function.

          class CNode
          {...
          int GetOrientation() const
          {
            CEmboss* pEmbossItem = dynamic_cast(m_pItem);
          
            if(pEmbossItem != NULL)
            {
              return pEmbossItem->GetOrientation();
            }
            else
            {
              // Error
              return ERROR_VALUE;
            }  
          }
          

          This works however only on polymorphic classes, this means classes with at least one virtual function.

          codito ergo sum

          1 Reply Last reply
          0
          • P piul

            Thank you guys. I must admit that I don't like very much the option proposed by Hanan888, because I would end up having a lot of methods in CItem that are used only in some of its derived classes. It would make CItem a bit messy. On the other hand, I'd considered using dynamic casting, but the book I'm reading says it is not recommendable. That it might be a sign of poor inheritance hierarchy design. I was just wondering if there was any other way.

            B Offline
            B Offline
            BadKarma
            wrote on last edited by
            #6

            piul wrote:

            On the other hand, I'd considered using dynamic casting, but the book I'm reading says it is not recommendable. That it might be a sign of poor inheritance hierarchy design.

            It might be a sign. It is not for fact a poor or bad design.

            codito ergo sum

            1 Reply Last reply
            0
            • P piul

              Hi there, I have a list in which each Node holds an object of the class CItem <pre></pre>

              class CList{
              ...
              CNode * mpListHead; };

              class CNode{
              double GetPos() const { return mpItem->GetPos(); }
              ...
              CItem * mpItem; };

              class CItem{
              double GetPos() const { return mdPosition; }
              ...
              double mdPosition; };

              Each Item can be of a different type

              class CEmboss : public CItem {...};
              class CAnneal : public CItem {...};

              And some of the items need to have some member data and functions that are not required in the rest, for example:

              class CEmboss : public CItem {
              ...
              int GetOrientation() const { return mnOrient; }
              ...
              int mnOrient; };

              The question is, how do I implement a GetOrientation() function in CNode?? I get a compiler error when mpItem->GetOrientation() because some of the Items don't have this method. One option is to put that function in CItem, even though it won't be used for some of the Items, but I'd prefer to put it only in CEmboss. Is there any way of doing this??

              CPalliniC Offline
              CPalliniC Offline
              CPallini
              wrote on last edited by
              #7

              piul wrote:

              The question is, how do I implement a GetOrientation() function in CNode??

              Probably the scenario will be clearer if you answer to the question "Why CNode needs to call GetOrientation?". I.e. must CNode retrieve always meaningful info with such a call? Generally speaking, there are two viable methods to overcome the problem: (1) use RTTI[^] to identify the actual type of the item. (2) go through polymorphism: declare a pure virtual GetOrientation method in CItem class thus forcing both CEmboss and C_Anneal_ to implement it. Personally I don't like method (1), but, of course, we have to choose the one that better fit our needs... :)

              If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
              This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke

              In testa che avete, signor di Ceprano?

              1 Reply Last reply
              0
              • P piul

                Thank you guys. I must admit that I don't like very much the option proposed by Hanan888, because I would end up having a lot of methods in CItem that are used only in some of its derived classes. It would make CItem a bit messy. On the other hand, I'd considered using dynamic casting, but the book I'm reading says it is not recommendable. That it might be a sign of poor inheritance hierarchy design. I was just wondering if there was any other way.

                C Offline
                C Offline
                Cedric Moonen
                wrote on last edited by
                #8

                piul wrote:

                On the other hand, I'd considered using dynamic casting, but the book I'm reading says it is not recommendable. That it might be a sign of poor inheritance hierarchy design.

                It seems that you didn't really understand this sentence ;) . It might be a sign of poor inheritance so, if you want to avoid using it, then you should review your inheritance and not make CEmboss inherits from CItem, but instead have a list with CEmboss objects only. That's why it says might, because it is not always possible to avoid it. The two suggested approaches (dynamic cast and virtual functions) have both their disadvantages: - dynamic cast will be a bit slower (but in the most cases, you won't even notice it, unless this code is heavily called) - virtual functions in your case make the code less readable (what is this GetOrientation function doing in my CItem class ??) It's up to you to decide.

                Cédric Moonen Software developer
                Charting control [v1.3]

                CPalliniC 1 Reply Last reply
                0
                • P piul

                  Thank you guys. I must admit that I don't like very much the option proposed by Hanan888, because I would end up having a lot of methods in CItem that are used only in some of its derived classes. It would make CItem a bit messy. On the other hand, I'd considered using dynamic casting, but the book I'm reading says it is not recommendable. That it might be a sign of poor inheritance hierarchy design. I was just wondering if there was any other way.

                  H Offline
                  H Offline
                  Hanan888
                  wrote on last edited by
                  #9

                  Hi, I assume you want to go over the list and do GetOrientation() to each node. If this node doesn't have 'orientation' , you want to know it doesn't have one. So, it will return NO_ORIENTATION. Another way -

                  typedef enum
                  {
                  eIT_UNDEFINED = 0,
                  eIT_ITEM,
                  eIT_EMBOSS,
                  eIT_ANNEAL,
                  } EItemType;

                  in CNode

                  EItemType m_eItemType;

                  int GetOrientation()
                  {
                  int result = NO_ORIENTATION;
                  switch (m_eItemType)
                  {
                  case eIT_EMBOSS:
                  {
                  result = ((CEmboss *) m_pItem)->GetOrientation();
                  break;
                  }
                  default:
                  break;
                  }
                  return result;
                  }

                  I can't think of any other way - if you want to do GetOrientation() on an object, it must have that method.

                  1 Reply Last reply
                  0
                  • C Cedric Moonen

                    piul wrote:

                    On the other hand, I'd considered using dynamic casting, but the book I'm reading says it is not recommendable. That it might be a sign of poor inheritance hierarchy design.

                    It seems that you didn't really understand this sentence ;) . It might be a sign of poor inheritance so, if you want to avoid using it, then you should review your inheritance and not make CEmboss inherits from CItem, but instead have a list with CEmboss objects only. That's why it says might, because it is not always possible to avoid it. The two suggested approaches (dynamic cast and virtual functions) have both their disadvantages: - dynamic cast will be a bit slower (but in the most cases, you won't even notice it, unless this code is heavily called) - virtual functions in your case make the code less readable (what is this GetOrientation function doing in my CItem class ??) It's up to you to decide.

                    Cédric Moonen Software developer
                    Charting control [v1.3]

                    CPalliniC Offline
                    CPalliniC Offline
                    CPallini
                    wrote on last edited by
                    #10

                    Cedric Moonen wrote:

                    - virtual functions in your case make the code less readable (what is this GetOrientation function doing in my CItem class ??)

                    I don't agree on the above point (I know it is matter of taste). Doing nothing is decorous for a method and maybe useful: nobody questions (at least I hope), for instance, on empty set usefulness (BTW doing nothing is one my preferred activities :-D ).

                    If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
                    This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke

                    In testa che avete, signor di Ceprano?

                    C 1 Reply Last reply
                    0
                    • CPalliniC CPallini

                      Cedric Moonen wrote:

                      - virtual functions in your case make the code less readable (what is this GetOrientation function doing in my CItem class ??)

                      I don't agree on the above point (I know it is matter of taste). Doing nothing is decorous for a method and maybe useful: nobody questions (at least I hope), for instance, on empty set usefulness (BTW doing nothing is one my preferred activities :-D ).

                      If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
                      This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke

                      C Offline
                      C Offline
                      Cedric Moonen
                      wrote on last edited by
                      #11

                      I think it depends of the situation. I was thinking about the case where you could have several child classes (5 or 6) and each of them needs one or two specific methods (and those methods only make sense in the child classes). Imagine the mess it would be :~ . And this situation is not that 'extreme'. Of course, it all depends of the situation.

                      CPallini wrote:

                      (BTW doing nothing is one my preferred activities ).

                      I thought it was surfing on CP :-D

                      Cédric Moonen Software developer
                      Charting control [v1.3]

                      1 Reply Last reply
                      0
                      • P piul

                        Hi there, I have a list in which each Node holds an object of the class CItem <pre></pre>

                        class CList{
                        ...
                        CNode * mpListHead; };

                        class CNode{
                        double GetPos() const { return mpItem->GetPos(); }
                        ...
                        CItem * mpItem; };

                        class CItem{
                        double GetPos() const { return mdPosition; }
                        ...
                        double mdPosition; };

                        Each Item can be of a different type

                        class CEmboss : public CItem {...};
                        class CAnneal : public CItem {...};

                        And some of the items need to have some member data and functions that are not required in the rest, for example:

                        class CEmboss : public CItem {
                        ...
                        int GetOrientation() const { return mnOrient; }
                        ...
                        int mnOrient; };

                        The question is, how do I implement a GetOrientation() function in CNode?? I get a compiler error when mpItem->GetOrientation() because some of the Items don't have this method. One option is to put that function in CItem, even though it won't be used for some of the Items, but I'd prefer to put it only in CEmboss. Is there any way of doing this??

                        M Offline
                        M Offline
                        Member 754960
                        wrote on last edited by
                        #12

                        This pattern presents a maintenance problem to me. What happens when you add more CItem types? How useful is CNode if the code needs to detect the type of the contents? The solution to me is to specialize the CNode class for the different CItems it holds,

                        // generic class
                        class CNode
                        {
                        public:
                        virtual bool process() = 0
                        {
                        // common default function
                        }
                        };

                        class CEmbossNode : public CNode
                        {
                        public:
                        virtual bool process()
                        {
                        // access CItem or CEmboss data/functions
                        return CNode::process(); // or call default
                        }
                        protected:
                        int GetOrientation() const { return mnOrient; }
                        private:
                        int mnOrient;
                        CEmboss * mpItem;
                        }

                        class CAnnealNode : public CNode
                        {
                        public:
                        virtual bool process()
                        {
                        // access CItem or CAnneal data/functions
                        // or call default
                        }
                        private:
                        CAnneal * mpItem;
                        };

                        class CList
                        {
                        // ...
                        CNode * mpListHead;
                        }

                        The types are hidden behind a polynorphic interface. Adding new types requires the definition of the polymorphic interface. Each CItem knows what it is and can use special knowledge or do just the default action. IMHO, these outwiegh the cost of the virtual function. // edit: remove multiple EmbossNode declarations

                        modified on Monday, March 24, 2008 1:43 PM

                        1 Reply Last reply
                        0
                        Reply
                        • Reply as topic
                        Log in to reply
                        • Oldest to Newest
                        • Newest to Oldest
                        • Most Votes


                        • Login

                        • Don't have an account? Register

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • World
                        • Users
                        • Groups