CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 7 of 7

Hybrid View

  1. #1
    Join Date
    Nov 2007
    Posts
    93

    Destroying an CArray of Cobject derived classes.

    I use a CArray<CClase1,CClase1> m_Clases1.

    CClase1 is derived of CObject. " class CClase1 : public CObject"

    When, at last I do : "m_Clases1.RemoveAll()" , I supose that the CClase1 destructor is called. But when i do this the program fails.
    IS there an evident reason for that? What i´mdoing wrong?

    THAnks.

  2. #2
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Destroying an CArray of Cobject derived classes.

    What error or exception are you seeing?

  3. #3
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Destroying an CArray of Cobject derived classes.

    Quote Originally Posted by pererm View Post
    IS there an evident reason for that? What i´mdoing wrong?
    Classes with improperly coded destructors, or while being used, corrupt memory, will have issues when the destructor is called.

    So we need to see this class you say is causing the error. More than likely, you don't even need to have a CArray of these classes to duplicate the error (I bet that your class is not safely copyable or assignable).

    Regards,

    Paul McKenzie

  4. #4
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Destroying an CArray of Cobject derived classes.

    Quote Originally Posted by pererm View Post
    I use a CArray<CClase1,CClase1> m_Clases1.

    CClase1 is derived of CObject. " class CClase1 : public CObject"
    So you're saying that this will also give you an error
    Code:
    class CClase1 : public CObject
    {
    };
    If you had an empty class, does the error occur? If not, then the reason for the problem is exactly as I described in my previous post -- your class implementation is buggy, causing memory corruption and/or issues with the destructor.

    Regards,

    Paul McKenzie

  5. #5
    Join Date
    Jan 2001
    Posts
    253

    Re: Destroying an CArray of Cobject derived classes.

    Deriving an class from CObject and then using it in a CArray directly (not as a pointer) requires additional work to be done in the class.
    The CObject class declares a private copy constructor and a private operator=. Both of these have no implementation.
    In order to use a class in a CArray which uses CObject as a base class, you need to implement these members in the derived class.

    The following shows a simple class which derives from CObject and can be used in a CArray:
    Code:
    class Test : public CObject
    {
    public:
       Test() : CObject()
       {
       }
       Test(const Test& source)
       {
       }
       Test& operator=(const Test& source)
       {
          return *this;
       }
    };
    
    void UseTest()
    {
       CArray<Test,Test> myTest;
       myTest.Add(Test());
       myTest.Add(Test());
       myTest.RemoveAll();
       
    }
    Note: it is unusual to do this with a class derived from CObject. Normally CObject is used as a base class for classes in MFC which are allocated. You wouldn't put the object itself into the collection but instead would put a pointer to the object. Since pointers can be copied or assigned without needing additional code, you wouldn't need to write the copy constructor and assignment operator.

    I would also suggest that you don't use CArray unless absolutely necessary. There are other containers in modern C++ which have better interfaces (like std::vector).

    Best regards,
    John

  6. #6
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    8,234

    Re: Destroying an CArray of Cobject derived classes.

    As jwbarton already said, CObject declares copy constructor and assignment operator as private, for the reason that can be seen in the following comments:
    Afx.h
    Code:
    	// Disable the copy constructor and assignment by default so you will get
    	//   compiler errors instead of unexpected behaviour if you pass objects
    	//   by value or assign objects.
    // ...
    private:
    	CObject(const CObject& objectSrc);              // no implementation
    	void operator=(const CObject& objectSrc);       // no implementation
    That's because many CObject-derived classes (CWnd and derived, CGdiObject and derived, CFile and derived, etc) keep a handle.
    There's not only a nonsense or a performance issue to keep the same handle in dfferent copies of an object but can be dangerous, leading (as stated above) in unexpected behavior. Let's say one of the copies is destroyed and inplicitly the handle is closed. The other ones will keep an invalid handle without "knowing" that.

    Here is an example of bad handle handling in a raw-WinAPI (non-MFC) application. During the release testing, the application reandomly crashed with no much clue.
    After wasted time and nerves, I found deep in the code something like this:
    Code:
    void CSomeClass::DoSomeCleaning()
    {
        // ...
        ::CloseHandle(m_hHandle);
    }
    In some rare situation, this function that closes a handle without further make it NULL (and written by a guy which never heard about RAII), was often called.
    I think the cause is now pretty clear: closing an invalid handle is evil.
    No mention the other situation (more often met) when try to USE an invalid handle.

    Returning to our sheep:
    Fortunately, MFC is well written from this point of view and helps us to avoid such mistakes.
    Besides tons of asserts showing at debug time the attempts of using invalid handles, it has this little "trick" of CObject which prevents making copies for objects that are keeping a handle.
    Of course, someone can derive then implement copy. He/she CAN but MAY NOT... except case he/she is knowing well he/she is doing (e.g. copy an object of a class derived from CObject that does not contains a handle).

    Quote Originally Posted by jwbarton View Post
    [...]
    I would also suggest that you don't use CArray unless absolutely necessary. There are other containers in modern C++ which have better interfaces (like std::vector).
    With the risk to wake up an old debate: please take a look at the quotes from may signature!
    I grabbed it from and old but good MFC book and wants to say: "If you are using MFC, then use MFC stuff".
    In other words, in code that uses MFC has no much sense to replace CArray with std::vector, CString with std::string, and so on.
    • "std::vector/std::string is better/faster/smaller/cooler than CArray/CString" is just a programming legend;
    • once using MFC which is NOT cross-platform, "cross-platform" argument becomes nonsense;
    • and so on.
    Last edited by ovidiucucu; November 23rd, 2013 at 11:04 AM.
    Ovidiu
    "When in Rome, do as Romans do."
    My latest articles: https://codexpertro.wordpress.com/

  7. #7
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Destroying an CArray of Cobject derived classes.

    Quote Originally Posted by ovidiucucu View Post
    With the risk to wake up an old debate: please take a look at the quotes from may signature!
    I grabbed it from and old but good MFC book and wants to say: "If you are using MFC, then use MFC stuff".
    In other words, in code that uses MFC has no much sense to replace CArray with std::vector, CString with std::string, and so on.
    • "std::vector/std::string is better/faster/smaller/cooler than CArray/CString" is just a programming legend;
    • once using MFC which is NOT cross-platform, "cross-platform" argument becomes nonsense;
    • and so on.
    I actually take the other approach - in that, the only time I use the MFC collections is when I need the CArchive ability when saving data to a file. Otherwise, I exclusively use the std collections. The reason for this is that the MFC collections are so clunky. I don't care about cross-platform, but I do care about readable code. Most if not all my apps are multi-threaded and it's fine to use the std collections between threads (as long as you synchronize access).

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured