解决方案 »

  1.   

    跟文件的写入、读取流一样?这里的“<<” 和 ">>"是不是重写了的呢?
      

  2.   

    CArchive类重载了operator << 和operator <<操作符
      

  3.   


    CArchive我貌似还没有用过...
      

  4.   

    对的,<< 和 >> 本是 C++ 里面的 插入操作符 和 提取操作符 。
    插入操作符 << 的作用是将它后面的内容插入到标准输出流中以便输出,而提取操作符 >> 的作用是从标准输入流中提取数据并存储到它后面的变量中。
    根据我的理解,
    所谓输入,就是程序运行的时候,从程序的外部拿数据进来使之成为程序自己的东西;
    所谓输出,就是程序运行的时候,把程序自己的数据送给外部以供外部来使用。
    下面的一段 C++ 代码说明了这两个操作符的用法:#include <iostream.h>
    void main()
    {
        int a;
        cout<<"Please enter an integer:\n";
        cin>>a;
        cout<<"a: "<<a<<endl;
    }再来说说你的这个代码:
    void CScribDoc::Serialize(CArchive& ar)
     {
       if (ar.IsStoring()) //如果是在存储归档文件(也就是把数据存储到文档中)
         ar << m_sizeDoc; //那么就将 m_sizeDoc 变量插入输出流中。这里输出流对象是 CArchive 类的对象 ar ,并且通常情况下 ar 已经和某个特定的文档关联起来了,那么将变量插入输出流中,就是将变量的值写入文档
       else //如果当前是在读取归档文件(也就是从文档中读取数据)
         ar >> m_sizeDoc; //同上。这里输入流对象是 ar ,那么就是从 ar 中提取数据并将数据保存到 m_sizeDoc 变量中
     m_graphList.Serialize(ar); //调用 m_graphList 的 Serialize 函数
     }
      

  5.   

    跟文件的写入、读取流一样?这里的“<<” 和 ">>"是不是重写了的呢?3楼说对了,就是重载了那两个符号,不过使用时候要注意写入顺序和读取顺序一致才行。
      

  6.   

    为此 MFC 的 CArchive 类重载了 << 和 >> 这两个操作符:
    为了让自定义类能够有永久保存功能,需要重载 << 和 >> 操作符,及其对serialize函数的重写,因此定义了宏DECLARE_SERIAL/IMPLEMENT_SERIAL
    #define DECLARE_SERIAL(class_name) \
     _DECLARE_DYNCREATE(class_name) \
     AFX_API friend CArchive& AFXAPI operator >>(CArchive& ar, class_name* &pOb); //友元函数重载>>操作符 #define IMPLEMENT_SERIAL(class_name, base_class_name, wSchema) \
     CObject* PASCAL class_name::CreateObject() \
      { return new class_name; } \
     extern AFX_CLASSINIT _init_##class_name; \
     _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, \
      class_name::CreateObject, &_init_##class_name) \
     AFX_CLASSINIT _init_##class_name(RUNTIME_CLASS(class_name)); \
     CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb) \
      { pOb = (class_name*) ar.ReadObject(RUNTIME_CLASS(class_name)); \
       return ar; } \为了在每一个对象被处理(读或写)之前,能够处理琐屑的工作,诸如判断是否是第一次出现、记录版本号码、记录文件名等工作,CRuntimeClass结构需要2个函数Load和Store:struct CRuntimeClass
    {
    // Attributes
     LPCSTR m_lpszClassName;
     int m_nObjectSize;
     UINT m_wSchema; // schema number of the loaded class
     CObject* (PASCAL* m_pfnCreateObject)(); // NULL => abstract class
    #ifdef _AFXDLL
     CRuntimeClass* (PASCAL* m_pfnGetBaseClass)();
    #else
     CRuntimeClass* m_pBaseClass;
    #endif// Operations
     CObject* CreateObject();
     BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const; // dynamic name lookup and creation
     static CRuntimeClass* PASCAL FromName(LPCSTR lpszClassName);
     static CRuntimeClass* PASCAL FromName(LPCWSTR lpszClassName);
     static CObject* PASCAL CreateObject(LPCSTR lpszClassName);
     static CObject* PASCAL CreateObject(LPCWSTR lpszClassName);// Implementation
     void Store(CArchive& ar) const;//存储类名称
     static CRuntimeClass* PASCAL Load(CArchive& ar, UINT* pwSchemaNum);//读取类名称 // CRuntimeClass objects linked together in simple list
     CRuntimeClass* m_pNextClass;       // linked list of registered classes
     const AFX_CLASSINIT* m_pClassInit;
    }; CRuntimeClass* PASCAL CRuntimeClass::Load(CArchive& ar, UINT* pwSchemaNum)
    {
        WORD nLen;
        char szClassName[64];
        CRuntimeClass* pClass;  
        ar >> (WORD&)(*pwSchemaNum) >> nLen;
        if(nLen >= sizeof(szClassName) || ar.Read(szClassName, nLen) != nLen )
            return NULL;
        szClassName[nLen] = '\0';
        for(pClass = pFirstClass; pClass != NULL; pClass = pClass->m_pNextClass)
        {
            if(llstrcmp(szClassName,pClass->m_lpszClassName) == 0)
                return pClass;
        }
        return NULL;
    }
    void CRuntimeClass::Store(CArchive& ar) const
    {
        WORD nLen = (WORD)lstrlenA(m_lpszClassName);
        ar << (WORD)m_wSchema << nLen;
        ar.Write(m_lpszClassName, nLen*sizeof(char));
    }
      

  7.   

    CArchive重写了这两个操作符。