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;
CArray fileArray;
};
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;
> CArray fileArray;
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."
--------------------+---------------------------------------------------
| Вернуться в корень Архива
|