0

ドキュメントの配列を作成するコードがいくつかあります。各ドキュメントオブジェクトには、ドキュメント全体の値の配列と、すべてのドキュメントデータを一緒に持つ個々のファイルの配列(それぞれが読み取り元のソースファイルの行であるため、行と呼ばれます)があります。ドキュメントオブジェクトを配列に追加しようとすると、以下のコピーコンストラクターが呼び出されます。

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();
}

問題は、後でドキュメント配列からドキュメントをプルしてアクセスしようとすると、上記でコピーした2つのアレイが空になることです。は初期化されており、メモリアドレスを持っているようですが、データが含まれていません。ただし、メンバー変数は設定されています。コピーを間違って行っているのか、それとも問題が他の場所にあるのかわかりません。

編集:通常のコンストラクターは次のようになります:

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の外でlpacLinesオブジェクトを使用しています。InitDocument私はすでにこのコードをデバッグしましたが、ここではすべてが正しく割り当てられています。

2番目の編集:これらすべての非ポインターメンバー変数を変換しようとすると、エラーC2248が発生します:'CObject :: CObject':クラス'CObject'で宣言されたプライベートメンバーにアクセスできません。振り返ってみると、このような問題が、そもそもポインタを使用するように私を駆り立てたのかもしれません。

3番目の編集:クラス宣言は次のとおりです。

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;
};
4

1 に答える 1

3

完全なクラス定義を投稿したので、実際に3つのルールに違反していることは明らかです。デストラクタ、コピーコンストラクタ、またはコピー代入演算子のいずれかを自分で明示的に宣言する必要がある場合は、おそらく3つすべてを明示的に宣言する必要があります。そのうちの。

コピーコンストラクタとデストラクタがありますが、コピー割り当てはありません。これらのメンバーを追加すれば、問題ないはずです。

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。コピー代入演算子がないため、コンパイラーは無駄にポインターをコピーします。これにより、2つの CMyDocumentオブジェクトが同じCArrayとを指すようになりCStringArrayます。次に、それらの1つが削除されるCArrayCStringArray、とが削除され、もう1CMyDocumentつには、無効なメモリを指す不要なポインタが残ります。その無効なメモリを使おうとすると、運が良ければ、以前はそこにあったものが表示されることがあります。この場合、空CArrayCStringArray。(削除されるとすぐに空になります)。運が悪ければ、プログラムは単にクラッシュしていたでしょう。

于 2013-03-26T23:37:43.203 に答える