Embedded Arrays
Farhad Sadaghiani -- hadi@interlog.com Thursday, October 24, 1996 Environment: VC++ 4.0, Windows 95 Hi, how's it going? Well, it's not going so good for me. I'm trying to make a CArray which has another CArray in it. Below are the two classes which are the TYPE for the CArray. class CFileInfo { public: CString strPath; CString strName; DWORD dwLength; }; class CDirInfo { public: LPARAM lParam; CString strDirName; CArrayfileArray; }; I then construct the CArray with no problem. CArray m_dirInfo; Now, when it comes to filling the array, I have a problem. I can add "fileinfo" to "dirinfo" successfully, but when I go to add "dirinfo" to "m_dirInfo" I get an error, namely: "error C2558: 'CDirInfo::CDirInfo' : no copy constructor available". Below is the code I use to add the arrays. void CTreeView1::SetupArray(CString name) { CDirInfo dirinfo; CFileInfo fileinfo; while ( ... ) { ... ... fileinfo.strPath = "Test_Path"; fileinfo.strName = "Test_Name"; fileinfo.dwLength = 0; // now add the "fileinfo" array into dirinfo dirinfo.fileArray.Add((CFileInfo) fileinfo); // this is successfull and works } // having exited the loop, it's time to add "dirinfo" (which contains an array of CFileInfo) // to the member variable m_dirInfo. m_dirInfo.Add((CDirInfo) dirinfo); // the above line causes the error: "error C2558: 'CDirInfo::CDirInfo' : no copy constructor available". // Below is the code I use to add the arrays } Please help me! Thanks.
Roger Onslow/Newcastle/Computer Systems Australia/ Monday, October 28, 1996 [Mini-digest: 3 responses] >class CFileInfo >{ >public: > CString strPath; > CString strName; > DWORD dwLength; >}; > >class CDirInfo >{ >public: > LPARAM lParam; > CString strDirName; > CArrayfileArray; I'd use CArray fileArray; passing args by reference (2nd param is type function args have) is nicer as no unnecessary copy to temporary involved. In general, if using any sort of struct or class as CArray elements, use a reference as second param. >}; > > >I then construct the CArray with no problem. > >CArray m_dirInfo; Same here -- use CDirInfo& for second parameter > > >Now, when it comes to filling the array, I have a problem. I can add >"fileinfo" to "dirinfo" successfully, but when I go to add "dirinfo" to >"m_dirInfo" I get an error, namely: "error C2558: 'CDirInfo::CDirInfo' : no >copy constructor available". Below is the code I use to add the arrays. no copy constructor because of CArray inside your CDirInfo -- compiler doesn't know how to do a default copy constructor because CArray doesn;t supply one. But this is just a symptom of the problem. >void CTreeView1::SetupArray(CString name) >{ > CDirInfo dirinfo; > CFileInfo fileinfo; > > while ( ... ) > { > ... > ... > fileinfo.strPath = "Test_Path"; > fileinfo.strName = "Test_Name"; > fileinfo.dwLength = 0; > > // now add the "fileinfo" array into dirinfo > dirinfo.fileArray.Add((CFileInfo) fileinfo); // this is successfull >and works Why cast a CFileInfo to CFileInfo in the above line .. seems redundant. Casts are dangerous things and should be avoided like the plague unless they are actually necessary. In anycase, you should try to use the static_cast, const_cast and reinterpret_cast operators instead of the old fashioned casts, as these new operators give more info to the compiler and the reader about WHY the cast is there anyway. > } > > // having exited the loop, it's time to add "dirinfo" (which contains an >array of CFileInfo) > // to the member variable m_dirInfo. > > m_dirInfo.Add((CDirInfo) dirinfo); > Yes, error because you have not told the compiler hoe to copy. You should use reference when defining the CArray to avoid the copy here However, that won't avoid *all* the copy (expensive) copy constructors, just the ones you can avoid. You will need to write your own copy constructor AND assignment operator for CDirInfo which explicitly says how to copy the CArray. > // the above line causes the error: "error C2558: 'CDirInfo::CDirInfo' : >no copy constructor available". // Below is the code I use to add the arrays > >} > >Please help me! Hope I have > >Thanks. You're welcome!! Roger Onslow RogerO@compsys.com.au Homer: "Operator! Give me the number for 911" (it's mfc-l@netcom.com :-) -----From: "Alexander(Sasha) Grinshpun" The reason for this phenomenon is that no copy constructor was defined for CDirInfo (that is what compiler said). When this constructor isn't defined by the user, the compiler tries to generate it for you by recursively calling copy constructors for base classes and data members of your class. In your case, it tries to apply copy constructors of LPARAM, CString and CArray<...>. For LPARAM and CString it works just fine, but CArray doesn't have user-defined copy constructor and compiler tries to generate it for you. CArray is derived from CObject that have private copy constructor (and assignment operator, btw). So compiler fails to generate copy constructor for this member and, as a consequence , for CDirInfo as a whole too. This design decision in MFC force you to explicitly define copy constructors and assignment that is a good practice anyway. So, all you have to do is to define CDirInfo::CDirInfo(const CDirInfo&) method. BTW, you can get more effective program by using reference to data as ARG_TYPE in CArray templates, e.g: CArray and CArray Thanks, Sasha. -----From: Mark Wright Farhad Sadaghiani wrote: > // now add the "fileinfo" array into dirinfo > dirinfo.fileArray.Add((CFileInfo) fileinfo); // this is successfull You don't need to cast fileinfo. > // having exited the loop, it's time to add "dirinfo" (which contains an > array of CFileInfo) > // to the member variable m_dirInfo. > > m_dirInfo.Add((CDirInfo) dirinfo); > > // the above line causes the error: "error C2558: 'CDirInfo::CDirInfo' : > no copy constructor available". // Below is the code I use to add the arrays Doing an Add(myvariable) requires a copy to take place. Your program knows how to copy an LPARAM and a CString (lParam and strDirName), but it doesn't know how to copy a CArray. You need to make fileArray an array with an operator= function. Create a class like: class CFileArray : public CArray { CFileArray& operator=( CFileArray& src ); }; And write an operator= function which will copy 'src' into 'this'. --------------------+--------------------------------------------------- Mark Wright | Steven King on the V-chip: (mswright@visi.com) | "if you want to put one in my remote control, | you'll have to pry it from my cold, dead hand." --------------------+---------------------------------------------------
| Вернуться в корень Архива |