深入浅出MFC第三章127页以及第八章405页都有提到class tag这里面提到这个字段值为 8001,是wOldClassTag|nClassIndex。 
于是我又翻到前面382页
这里有下面的代码  void CArchive::WriteClass(const CRuntimeClass* pClassRef)
  {
    if(nClassIndex=(DWORD)(*m_pStoreMap)[(void *)pClassRef])!=)
     {
        if(nClassIndex<wBigObjectTag)
           *this<<(WORD)(wClassTag|nClassIndex);
        else
         {
            *this<<wBigObjectTag;
            *this<<(dwBigClassTag|nClassIndex);
         }
      }
    else
     {
           *this<<wNewClassTag;
           pClassRef->Store(*this);
      }
   }
 。。问题来了。。
1.这个nClassIndex具体是做什么用的?
2.代码里面的第五行  if(nClassIndex<wBigObjectTag) 所做的判断是什么意思?下面几行根据判断所做出的操作是什么?
3.这个貌似跟IMPLEMENT_SERIAL(class_name,base_class_name,wSchema)里面的第三个参数有关,请问这第三个参数是什么?麻烦各位帮我解释下这些疑惑。。最好不要“只|贴网址解答。。找答案真的很晕~~

解决方案 »

  1.   

    1. nClassIndex用于存储pClassRef的类信息。从m_pStoreMap处获取,m_pStoreMap是一个Map变量。
    2. if(nClassIndex <wBigObjectTag)用于判断nClassIndex是一个对象标志还是一个类标志。
       #define dwBigClassTag   ((DWORD)0x80000000) // 0x8000000 indicates big class tag (OR'd)
       #define wBigObjectTag   ((WORD)0x7FFF)      // 0x7FFF indicates DWORD object tag
    void CArchive::WriteObject(const CObject* pOb)
    {         // 对象可以为 NULL
    DWORD nObIndex;
             // 初始化m_pStoreMap
             MapObject(NULL);         if (pOb == NULL)
             {
                       // 保存NULL指针标志
                       *this << wNullTag;
             }
             else if ((nObIndex = (DWORD)(*m_pStoreMap)[(void*)pOb]) != 0)
                       // assumes initialized to 0 map
             {
                       //保存已存储过对象的INDEX
                       if (nObIndex < wBigObjectTag)
                                *this << (WORD)nObIndex;
                       else
                       {
                                *this << wBigObjectTag;
                                *this << nObIndex;
                       }
             }
             else
             {
                       // 写入示保存过的对象
                      CRuntimeClass* pClassRef = pOb->GetRuntimeClass();
                      WriteClass(pClassRef);
                       // enter in stored object table, checking for overflow
                      CheckCount();
                      (*m_pStoreMap)[(void*)pOb] = (void*)m_nMapCount++;                   // 使对象自身进行系列化
                      ((CObject*)pOb)->Serialize(*this);
             }
    }
      

  2.   

    void CArchive::WriteClass(const CRuntimeClass* pClassRef)
    {
             // 确认pStoreMap已被初始化
             MapObject(NULL);//在这里实际没有做什么事情
             // 写入对象的ID和指示符并把指示符放在高位.
             // new object follows
             //假定map以初始化为0
             DWORD nClassIndex;
             if ((nClassIndex = (DWORD)(*m_pStoreMap)[(void*)pClassRef]) != 0)
             {
                       // previously seen class, write out the index tagged by high bit
                       if (nClassIndex < wBigObjectTag)
                                *this << (WORD)(wClassTag nClassIndex);
                       else
                       {
                                *this << wBigObjectTag;
                                *this << (dwBigClassTag nClassIndex);
                       }
             }
             else
             {
                       // 存储新对象
                       *this << wNewClassTag;
                       //存储RUNTIME_CLASS对象所需的信息(如:对象名字)                  pClassRef->Store(*this);
                       // 存储新对象的引用(参考)到MAP中
                      CheckCount();
                      (*m_pStoreMap)[(void*)pClassRef] = (void*)m_nMapCount++;
             }
    }另外补充一些知识Tag(标识符)                   Description(描述)
    wNullTag                   用于一个指向NULL的对象.
    wNewClassTag               指出其后面是一个新的对象
    wOldClassTag               指出将要读取的是一个已读取过的对象
    wClassTag                  类指示符
    dwBigClassTag              0x80000000 指示一个大类标志
    wBigObjectTag              0x7FFF 指示一个大对象标记
    nMaxMapCount               0x3FFFFFFE 表示最大的mapCount值
      

  3.   

    其实简单来说,class tag 就是要写入或者读出来的类的标志吧。
    nClassIndex 就是这个类标志的索引值。
    #define wNullTag        ((WORD)0)           // special tag indicating NULL ptrs
    #define wNewClassTag    ((WORD)0xFFFF)      // special tag indicating new CRuntimeClass
    #define wClassTag       ((WORD)0x8000)      // 0x8000 indicates class tag (OR'd)
    #define dwBigClassTag   ((DWORD)0x80000000) // 0x8000000 indicates big class tag (OR'd)
    #define wBigObjectTag   ((WORD)0x7FFF)      // 0x7FFF indicates DWORD object tag
    #define nMaxMapCount    ((DWORD)0x3FFFFFFE) // 0x3FFFFFFE last valid mapCount
    // This is how the tags have been allocated currently:
    //
    //  0x0000              represents NULL pointer
    //  0x0001 - 0x7FFE     "small" object tags
    //  0x7FFF              header for "big" object/class tag
    //  0x8000              reserved for future use
    //  0x8001 - 0xFFFE     "small" class tag
    //  0xFFFF              header for class definition
    //
    // The special value of 0x7FFF indicates that a DWORD tag follows.  This
    // two part "big" tag is used for 32-bit tag values 0x7FFF and above.
    // The tag value of 0x7FFF was unused in MFC versions prior to MFC 4.0.2.代码里面的第五行  if(nClassIndex <wBigObjectTag) 所做的判断是什么意思?下面几行根据判断所做出的操作是什么?判断索引值是否超出了,小类标志( "small" class tag)的范围,如果没有就直接)(wClassTag|nClassIndex); 与wClassTag 或操作是为了区分 类 还是 对象。如果超出范围就 *this<<wBigObjectTag;
                *this<<(dwBigClassTag|nClassIndex);
    这里不多解释了,就是范围超出了wClassTag,必须找个更大的数dwBigClassTag来与索引组成组合值。第一个*this<<wBigObjectTag; 是为了读类的时候ReadClass函数 那里处理方便,先获取到的wBigObjectTag,判断出是一个大范围的类标志("big" class tag) 3.这个貌似跟IMPLEMENT_SERIAL(class_name,base_class_name,wSchema)里面的第三个参数有关,请问这第三个参数是什么? 没有直接关系,wSchema是一个archive版本号而已。这3个参数分别是,IMPLEMENT_SERIAL所在的那个类,所在那个类的基类,archive的版本号。例如,MSDN上的例子:
    // MyClass.cpp
    #include "stdafx.h"
    #include "MyClass.h"IMPLEMENT_SERIAL( CMyClass, CObject, VERSIONABLE_SCHEMA | 2 )...