我有一些代码可以创建一个文档数组。每个文档对象都有一个文档范围的值数组,以及一个单独的文件数组(称为行,因为每个文件都是我正在读取的源文件中的一行),它们共同拥有所有文档数据。当我尝试将文档对象添加到数组时,它正在调用我的复制构造函数:
CMyDocument::CMyDocument(CMyDocument& cSourceDoc)
{
m_lpastrFields = new CStringArray;
m_lpacLines = new CArray<CMyLine, CMyLine>;
int nCount;
int nSize;
nSize = static_cast<int>(cSourceDoc.GetFields()->GetSize());
for (nCount = 0; nCount < nSize; nCount++)
{
m_lpastrFields->Add(cSourceDoc.GetFields()->GetAt(nCount));
}
nSize = static_cast<int>(cSourceDoc.GetLines()->GetSize());
for (nCount = 0; nCount < nSize; nCount++)
{
m_lpacLines->Add(cSourceDoc.GetLines()->GetAt(nCount));
}
m_strDocDate = cSourceDoc.GetDocDate();
m_nDocID = cSourceDoc.GetDocID();
m_strDocType = cSourceDoc.GetDocType();
}
问题是,当我稍后通过从文档数组中提取文档来尝试访问文档时,我上面复制的两个数组都是空的。似乎已初始化并具有内存地址,但它们不包含任何数据。但是会填充成员变量。我不确定我是否正在进行错误的复制,或者问题是否在其他地方。
编辑:常规构造函数如下所示:
CMyDocument::CMyDocument()
{
m_lpastrFields = new CStringArray;
}
在这种情况下,我没有新建m_lpacLines
对象,因为它是通过一个名为InitDocument的函数传递给MyDocument对象的。我可以在这里包括它。 (为了简洁起见,一些不必要的细节,比如我解析strLine
变量以提取所有值的方式,被修剪了。
void CMyDocument::InitDocument(CMyColumns* lpcColumns, CString strLine, CArray<CMyLine, CMyLine>* lpacLines)
{
CString strValue;
CString strComma = ",";
int nPos = 0;
m_lpacLines = lpacLines;
while (-1 != nPos)
{
strValue = strLine.Tokenize(strComma, nPos);
m_lpastrFields->Add(strValue);
}
m_strDocDate = m_lpastrFields->GetAt(lpcColumns->GetDocDateIndex());
CString strDocID = m_lpastrFields->GetAt(lpcColumns->GetDocIDIndex());
m_nDocID = atoi(strDocID);
m_strDocType = m_lpastrFields->GetAt(lpcColumns->GetDocTypeIndex());
}
要清楚,每次循环时,我new
InitDocument
函数之外的class CMyDocument
{
public:
CMyDocument();
~CMyDocument();
CMyDocument(CMyDocument& cSourceDoc);
void InitDocument(CMyColumns* lpcColumns, CString strLine, CArray<CMyLine, CMyLine>* lpacLines);
inline CString GetDocDate(void) {return(m_strDocDate);};
inline int GetDocID(void) {return(m_nDocID);};
inline CString GetDocType(void) {return(m_strDocType);};
inline CStringArray* GetFields(void) {return(m_lpastrFields);};
inline CArray<CMyLine, CMyLine>* GetLines(void) {return m_lpacLines;};
private:
CArray<CMyLine, CMyLine>* m_lpacLines;
CStringArray* m_lpastrFields;
CString m_strDocDate;
int m_nDocID;
CString m_strDocType;
};
lpacLines对象。我已经调试了这段代码,所有内容都在这里正确分配。
SECOND EDIT:在尝试转换所有非指针成员变量时,我现在遇到错误C2248:'CObject :: CObject':无法访问类中声明的私有成员' CObject的”。经过反思,这样的问题可能是推动我首先使用指针的原因。
第三次编辑:这是类声明:
{{1}}
答案 0 :(得分:3)
现在您已经发布了完整的类定义,很明显您确实违反了Rule of Three:如果您需要自己显式声明析构函数,复制构造函数或复制赋值运算符,您可能需要明确声明所有这三个。
你有一个复制构造函数和一个析构函数,但是没有复制的assignemnt。添加这些成员,你应该没事。
CMyDocument& operator=(CMyDocument cSourceDoc) {
swap(cSourceDoc);
return *this;
}
void swap(CMyDocument& cSourceDoc) {
using std::swap;
swap(m_lpacLines, cSourceDoc.m_lpacLines);
swap(m_lpastrFields, cSourceDoc.m_lpastrFields);
swap(m_strDocDate, cSourceDoc.m_strDocDate);
swap(m_nDocID, cSourceDoc.m_nDocID);
swap(m_strDocType, cSourceDoc.m_strDocType);
}
您的构造函数分配内存,并为其指定成员。在代码的某处,您正在制作CMyDocument
的副本。由于您没有复制赋值运算符,编译器无用地为您创建一个,只需复制指针,以便您有两个 CMyDocument
个对象指向同一个CArray
和CStringArray
。然后,当其中一个被删除时,他们会删除CArray
和CStringArray
,而另一个CMyDocument
会留下指向无效内存的无用指针。当你试图使用那个无效的记忆时,有时候,如果你运气好的话,你会看到曾经存在的东西。在这种情况下,空CArray
和CStringArray
。 (他们在删除时自行清空)。如果你不幸运,程序就会崩溃。