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
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Is this good form?

Is this good form?

Scheduled Pinned Locked Moved C / C++ / MFC
questionc++
7 Posts 3 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.
  • C Offline
    C Offline
    Cloaca
    wrote on last edited by
    #1

    Hello everyone, I have been working on an MFC SDI program whose Document actually has lists of lists (and possibly a list of a list of a list). I would like to get into a good habit and be consistent with the way I maintain collections (mostly lists, occasionally arrays and maps). Almost all my objects are derived from CObject (for serializing, etc.). I guess it comes down to picking between CList, CList, CList and whatever other combinations. To keep sane, I think I always want to use CList. That way, I just use the new operator at the point where an object needs to be instantiated and call delete on it (while traversing the list or sublist) at the 'outer' list's destructor. I would like comments about this. Is it safe? Is it a decent practice to keep? How can I prevent double deleting the same objects (if that could even happen)? Does this choice affect how I code the required copy constructor and assignment operator (which always seem to involve references)? Thanks in advance for any advice and comments! Eric

    C M 2 Replies Last reply
    0
    • C Cloaca

      Hello everyone, I have been working on an MFC SDI program whose Document actually has lists of lists (and possibly a list of a list of a list). I would like to get into a good habit and be consistent with the way I maintain collections (mostly lists, occasionally arrays and maps). Almost all my objects are derived from CObject (for serializing, etc.). I guess it comes down to picking between CList, CList, CList and whatever other combinations. To keep sane, I think I always want to use CList. That way, I just use the new operator at the point where an object needs to be instantiated and call delete on it (while traversing the list or sublist) at the 'outer' list's destructor. I would like comments about this. Is it safe? Is it a decent practice to keep? How can I prevent double deleting the same objects (if that could even happen)? Does this choice affect how I code the required copy constructor and assignment operator (which always seem to involve references)? Thanks in advance for any advice and comments! Eric

      C Offline
      C Offline
      Christian Graus
      wrote on last edited by
      #2

      Cloaca wrote: To keep sane, I think I always want to use CList. MFC containers are utter crap. Use std::list instead and you'll find a lot of the ancillary code you need to write will already be there for you. Christian I have drunk the cool-aid and found it wan and bitter. - Chris Maunder

      C 1 Reply Last reply
      0
      • C Christian Graus

        Cloaca wrote: To keep sane, I think I always want to use CList. MFC containers are utter crap. Use std::list instead and you'll find a lot of the ancillary code you need to write will already be there for you. Christian I have drunk the cool-aid and found it wan and bitter. - Chris Maunder

        C Offline
        C Offline
        Cloaca
        wrote on last edited by
        #3

        Thanks for your tip Christian. I will look around to learn how to make std::list (part of the STL, right?) work with MFC (including topics like Serialization, etc.). If you could suggest any resources in particular, that would be great. Thanks again! :-) Eric

        1 Reply Last reply
        0
        • C Cloaca

          Hello everyone, I have been working on an MFC SDI program whose Document actually has lists of lists (and possibly a list of a list of a list). I would like to get into a good habit and be consistent with the way I maintain collections (mostly lists, occasionally arrays and maps). Almost all my objects are derived from CObject (for serializing, etc.). I guess it comes down to picking between CList, CList, CList and whatever other combinations. To keep sane, I think I always want to use CList. That way, I just use the new operator at the point where an object needs to be instantiated and call delete on it (while traversing the list or sublist) at the 'outer' list's destructor. I would like comments about this. Is it safe? Is it a decent practice to keep? How can I prevent double deleting the same objects (if that could even happen)? Does this choice affect how I code the required copy constructor and assignment operator (which always seem to involve references)? Thanks in advance for any advice and comments! Eric

          M Offline
          M Offline
          Mike Dimmick
          wrote on last edited by
          #4

          It depends whether you want homogeneous (containing one type of object only) or heterogeneous (containing multiple types of object) containers. If I want a homogeneous container, I typically have the container manage the storage of the contained objects. If the objects are small (perhaps ints), I use a CList< int, int >. If the objects are larger than about 8 bytes, I use CList< T, const T& > so that any functions which need an object (to store it, or compare it) take their argument by constant reference. You don't need to do any extra clean-up when you destroy the container; it destroys all the elements for you. For a concrete definition of a heterogeneous container, consider a class hierarchy modelling shapes. We have an abstract base class CShape with derived classes CRectangle, CEllipse and CPolygon (for example). We want the container to be able to hold any combination of rectangles, ellipses, polygons and whatever else we might define in future. To get polymorphic behaviour, we must store base class pointers. So I would normally declare the container as storing pointers of the type of the most-derived base class common to the elements to be contained. In this case I would use a CList< CShape*, CShape* >. The ARGTYPE is a CShape* because pointers are trivial to copy. Lists of lists are tricky in MFC because CList doesn't define a copy constructor or assignment operator. You can't contain a CList inside a CList (although you can store CList pointers). If the top-level list is heterogeneous, you probably do need to use a list of CObject pointers, and MFC has a special class for that: CObList.

          C 1 Reply Last reply
          0
          • M Mike Dimmick

            It depends whether you want homogeneous (containing one type of object only) or heterogeneous (containing multiple types of object) containers. If I want a homogeneous container, I typically have the container manage the storage of the contained objects. If the objects are small (perhaps ints), I use a CList< int, int >. If the objects are larger than about 8 bytes, I use CList< T, const T& > so that any functions which need an object (to store it, or compare it) take their argument by constant reference. You don't need to do any extra clean-up when you destroy the container; it destroys all the elements for you. For a concrete definition of a heterogeneous container, consider a class hierarchy modelling shapes. We have an abstract base class CShape with derived classes CRectangle, CEllipse and CPolygon (for example). We want the container to be able to hold any combination of rectangles, ellipses, polygons and whatever else we might define in future. To get polymorphic behaviour, we must store base class pointers. So I would normally declare the container as storing pointers of the type of the most-derived base class common to the elements to be contained. In this case I would use a CList< CShape*, CShape* >. The ARGTYPE is a CShape* because pointers are trivial to copy. Lists of lists are tricky in MFC because CList doesn't define a copy constructor or assignment operator. You can't contain a CList inside a CList (although you can store CList pointers). If the top-level list is heterogeneous, you probably do need to use a list of CObject pointers, and MFC has a special class for that: CObList.

            C Offline
            C Offline
            Cloaca
            wrote on last edited by
            #5

            Hi Mike, I appreciate your response. From what you wrote it looks like if I need to maintain a collection of different objects (but all derived from a common base), then a CList< baseclass*, basclass*> is the way to go (which is what I had been thinking for 'my sanity's sake'). For trivially small things (e.g. ints), a CList is good. This sounds good to me. You wrote: "If the objects are larger than about 8 bytes, I use CList< T, const T& > so that any functions which need an object (to store it, or compare it) take their argument by constant reference." What is the advantage of doing CList over CList ? Or, alternatively, is there a reason not to do CList all the time? Thanks again! Eric

            M 1 Reply Last reply
            0
            • C Cloaca

              Hi Mike, I appreciate your response. From what you wrote it looks like if I need to maintain a collection of different objects (but all derived from a common base), then a CList< baseclass*, basclass*> is the way to go (which is what I had been thinking for 'my sanity's sake'). For trivially small things (e.g. ints), a CList is good. This sounds good to me. You wrote: "If the objects are larger than about 8 bytes, I use CList< T, const T& > so that any functions which need an object (to store it, or compare it) take their argument by constant reference." What is the advantage of doing CList over CList ? Or, alternatively, is there a reason not to do CList all the time? Thanks again! Eric

              M Offline
              M Offline
              Mike Dimmick
              wrote on last edited by
              #6

              I prefer the version without the pointers for three reasons:

              1. I don't have to clean up the list myself (CList doesn't delete objects pointed to in the destructor).
              2. I don't have to handle indirections.
              3. The list has less memory-management overhead.

              I'll deviate from this if I have to store references to the same object in multiple places in a list, but this is less common.

              C 1 Reply Last reply
              0
              • M Mike Dimmick

                I prefer the version without the pointers for three reasons:

                1. I don't have to clean up the list myself (CList doesn't delete objects pointed to in the destructor).
                2. I don't have to handle indirections.
                3. The list has less memory-management overhead.

                I'll deviate from this if I have to store references to the same object in multiple places in a list, but this is less common.

                C Offline
                C Offline
                Cloaca
                wrote on last edited by
                #7

                Hi Mike, Thanks again. About reason 1.: Most times, the objects that are in a list are made using a call to 'new' at some point in the code. If this is the case, then the contents of the list (the newed objects) need to get deleted at some point anyway. And this must be done by walking through the list in a loop to call delete for each item before doing a RemoveAll() on the list. Or, do you have a methodology in coding that 'recycles' objects. That is, a variable of type CMyObject is declared and reused (has its data changed) whenever an item needs to be added to the list. Then, due to storing actual T's (not T*'s or T&'s), they are passed by reference into the CList by value (so that the declared variable can be changed for reuse to create the next item in the list). Is this what you mean? Does this mean that the destructor for each item in the list is called when the CList is destroyed? Thanks very much, Eric

                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