📄 classdef.cpp
字号:
//----------------------------------------------------------------------------/*! * recusively merges the `all members' lists of a class base * with that of this class. Must only be called for classes without * subclasses! */void ClassDef::mergeMembers(){ BaseClassListIterator bcli(*baseClasses()); BaseClassDef *bcd; for ( ; (bcd=bcli.current()) ; ++bcli ) { ClassDef *bClass=bcd->classDef; // merge the members in the base class of this inheritance branch first bClass->mergeMembers(); MemberNameInfoSDict *srcMnd = bClass->memberNameInfoSDict(); MemberNameInfoSDict *dstMnd = memberNameInfoSDict(); //MemberNameInfoList *dstMnl = memberNameInfoList(); MemberNameInfoSDict::Iterator srcMnili(*srcMnd); MemberNameInfo *srcMni; for ( ; (srcMni=srcMnili.current()) ; ++srcMnili) { //printf("Base member name %s\n",srcMni->memberName()); MemberNameInfo *dstMni; if ((dstMni=dstMnd->find(srcMni->memberName()))) // a member with that name is already in the class. // the member may hide or reimplement the one in the sub class // or there may be another path to the base class that is already // visited via another branch in the class hierarchy. { MemberNameInfoIterator srcMnii(*srcMni); MemberInfo *srcMi; for ( ; (srcMi=srcMnii.current()) ; ++srcMnii ) { MemberDef *srcMd = srcMi->memberDef; bool found=FALSE; bool ambigue=FALSE; bool hidden=FALSE; MemberNameInfoIterator dstMnii(*dstMni); MemberInfo *dstMi; ClassDef *srcCd = srcMd->getClassDef(); for ( ; (dstMi=dstMnii.current()) && !found; ++dstMnii ) { MemberDef *dstMd = dstMi->memberDef; if (srcMd!=dstMd) // different members { ClassDef *dstCd = dstMd->getClassDef(); //printf("Is %s a base class of %s?\n",srcCd->name(),dstCd->name()); if (srcCd==dstCd || dstCd->isBaseClass(srcCd)) // member is in the same or a base class { found=matchArguments(srcMd->argumentList(), dstMd->argumentList() ); //ambigue = ambigue || !found; hidden = hidden || !found; } else // member is in a non base class => multiple inheritance // using the same base class. { //printf("$$ Existing member %s %s add scope %s\n", // dstMi->ambiguityResolutionScope.data(), // dstMd->name().data(), // dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data()); QCString scope=dstMi->scopePath.left(dstMi->scopePath.find("::")+2); if (scope!=dstMi->ambiguityResolutionScope.left(scope.length())) dstMi->ambiguityResolutionScope.prepend(scope); ambigue=TRUE; } } else // same members { // do not add if base class is virtual or // if scope paths are equal if ((srcMi->virt==Virtual && dstMi->virt==Virtual) || bClass->name()+"::"+srcMi->scopePath == dstMi->scopePath ) { found=TRUE; } else // member can be reached via multiple paths in the // inheritance tree { //printf("$$ Existing member %s %s add scope %s\n", // dstMi->ambiguityResolutionScope.data(), // dstMd->name().data(), // dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data()); QCString scope=dstMi->scopePath.left(dstMi->scopePath.find("::")+2); if (scope!=dstMi->ambiguityResolutionScope.left(scope.length())) dstMi->ambiguityResolutionScope.prepend(scope); ambigue=TRUE; } } } //printf("member %s::%s hidden %d ambigue %d srcMi->ambigClass=%p\n", // srcCd->name().data(),srcMd->name().data(),hidden,ambigue,srcMi->ambigClass); // TODO: fix the case where a member is hidden by inheritance // of a member with the same name but with another prototype, // while there is more than one path to the member in the // base class due to multiple inheritance. In this case // it seems that the member is not reachable by prefixing a // scope name either (according to my compiler). Currently, // this case is shown anyway. if (!found && srcMd->protection()!=Private) { Specifier virt=srcMi->virt; if (srcMi->virt==Normal && bcd->virt!=Normal) virt=bcd->virt; MemberInfo *newMi = new MemberInfo(srcMd,bcd->prot,virt,TRUE); newMi->scopePath=bClass->name()+"::"+srcMi->scopePath; if (ambigue) { //printf("$$ New member %s %s add scope %s::\n", // srcMi->ambiguityResolutionScope.data(), // srcMd->name().data(), // bClass->name().data()); QCString scope=bClass->name()+"::"; if (scope!=srcMi->ambiguityResolutionScope.left(scope.length())) newMi->ambiguityResolutionScope= scope+srcMi->ambiguityResolutionScope.copy(); } if (hidden) { if (srcMi->ambigClass==0) { newMi->ambigClass=bClass; newMi->ambiguityResolutionScope=bClass->name()+"::"; } else { newMi->ambigClass=srcMi->ambigClass; newMi->ambiguityResolutionScope=srcMi->ambigClass->name()+"::"; } } //printf("Adding!\n"); dstMni->append(newMi); } } } else // base class has a member that is not in the sub class => copy { // create a deep copy of the list (only the MemberInfo's will be // copied, not the actual MemberDef's) MemberNameInfo *newMni = new MemberNameInfo(srcMni->memberName()); // copy the member(s) from the base to the sub class MemberNameInfoIterator mnii(*srcMni); MemberInfo *mi; for (;(mi=mnii.current());++mnii) { Protection prot = mi->prot; if (bcd->prot==Protected) { if (prot==Public) prot=Protected; } else if (bcd->prot==Private) { prot=Private; } //printf("%s::%s: prot=%d bcd->prot=%d result=%d\n", // name().data(),mi->memberDef->name().data(),mi->prot, // bcd->prot,prot); if (mi->prot!=Private) { Specifier virt=mi->virt; if (mi->virt==Normal && bcd->virt!=Normal) virt=bcd->virt; //printf("Adding!\n"); MemberInfo *newMi=new MemberInfo(mi->memberDef,prot,virt,TRUE); newMi->scopePath=bClass->name()+"::"+mi->scopePath; newMi->ambigClass=mi->ambigClass; newMi->ambiguityResolutionScope=mi->ambiguityResolutionScope.copy(); newMni->append(newMi); } } // add it to the dictionary //dstMnl->append(newMni); dstMnd->append(newMni->memberName(),newMni); } } }}//----------------------------------------------------------------------------void ClassDef::addUsedClass(ClassDef *cd,const char *accessName){ if (m_usesImplClassDict==0) m_usesImplClassDict = new UsesClassDict(17); UsesClassDef *ucd=m_usesImplClassDict->find(cd->name()); if (ucd==0 /*|| ucd->templSpecifiers!=templSpec*/) { ucd = new UsesClassDef(cd); m_usesImplClassDict->insert(cd->name(),ucd); //ucd->templSpecifiers = templSpec; //printf("Adding used class %s to class %s\n", // cd->name().data(),name().data()); } ucd->addAccessor(accessName);}#if 0/*! Builds up a dictionary of all classes that are used by the state of this * class (the "implementation"). * Must be called before mergeMembers() is called! */void ClassDef::determineImplUsageRelation(){ MemberNameInfoSDict::Iterator mnili(*m_allMemberNameInfoSDict); MemberNameInfo *mni; for (;(mni=mnili.current());++mnili) { MemberNameInfoIterator mnii(*mni); MemberInfo *mi; for (mnii.toFirst();(mi=mnii.current());++mnii) { MemberDef *md=mi->memberDef; if (md->isVariable()) // for each member variable in this class { QCString type=removeRedundantWhiteSpace(md->typeString()); //printf("in class %s found var type=`%s' name=`%s'\n", // name().data(),type.data(),md->name().data()); int pos=0; QCString usedClassName; QCString templSpec; bool found=FALSE; while (extractClassNameFromType(type,pos,usedClassName,templSpec) && !found) { //printf("usedClassName=`%s' templSpec=%s\n",usedClassName.data(),templSpec.data()); // check if usedClassName is a template argument of its class ClassDef *cd=md->getClassDef(); if (cd && cd->templateArguments()) { ArgumentListIterator ali(*cd->templateArguments()); Argument *arg; int count=0; for (ali.toFirst();(arg=ali.current());++ali,++count) { if (arg->name==usedClassName) // type is a template argument { found=TRUE; if (m_usesImplClassDict==0) m_usesImplClassDict = new UsesClassDict(257); cd = new ClassDef(cd->getDefFileName(),cd->getDefLine(), usedClassName,ClassDef::Class); cd->setIsTemplateBaseClass(count); UsesClassDef *ucd = new UsesClassDef(cd); m_usesImplClassDict->insert(cd->name(),ucd); ucd->templSpecifiers = templSpec; ucd->addAccessor(md->name()); Doxygen::hiddenClasses.append(cd); //printf("Adding used template argument %s to class %s\n", // cd->name().data(),name().data()); //printf("Adding accessor %s to class %s\n", // md->name().data(),ucd->classDef->name().data()); } } } if (!found) { cd=0; if (getNamespaceDef()!=0) { cd=getResolvedClass(getNamespaceDef()->name()+"::"+usedClassName,0,&templSpec); } if (cd==0) cd=getResolvedClass(name()+"::"+usedClassName,0,&templSpec); if (cd==0) cd=getResolvedClass(usedClassName,0,&templSpec); // TODO: also try inbetween scopes! //printf("Search for class %s result=%p\n",usedClassName.data(),cd); if (cd) // class exists { found=TRUE; if (m_usesImplClassDict==0) m_usesImplClassDict = new UsesClassDict(257); UsesClassDef *ucd=m_usesImplClassDict->find(cd->name()); if (ucd==0 || ucd->templSpecifiers!=templSpec) { ucd = new UsesClassDef(cd); m_usesImplClassDict->insert(cd->name(),ucd); ucd->templSpecifiers = templSpec; //printf("Adding used class %s to class %s\n", // cd->name().data(),name().data()); } ucd->addAccessor(md->name()); //printf("Adding accessor %s to class %s\n", // md->name().data(),ucd->classDef->name().data()); } } } } } }#ifdef DUMP if (m_usesClassDict) { msg("Class %s uses the following classes:\n",name().data()); UsesClassDictIterator ucdi(*m_usesClassDict); UsesClassDef *ucd; for (;(ucd=ucdi.current());++ucdi) { msg(" %s via ",ucd->classDef->name().data()); QDictIterator<void> dvi(*ucd->accessors); const char *s; for (;(s=dvi.currentKey());++dvi) { msg("%s ",s); } msg("\n"); } }#endif}//----------------------------------------------------------------------------// I have disabled this code because the graphs it renders quickly become// too large to be of practical use.void ClassDef::addUsedInterfaceClasses(MemberDef *md,const char *typeStr){ QCString type = typeStr; static const QRegExp re("[a-z_A-Z][a-z_A-Z0-9:]*"); int p=0,i,l; while ((i=re.match(type,p,&l))!=-1) // for each class name in the type { ClassDef *cd=getClass(name()+"::"+type.mid(i,l)); if (cd==0) cd=getClass(type.mid(i,l)); // TODO: also try inbetween scopes! if (cd && cd!=this && !isBaseClass(cd)) { if (m_usesIntfClassDict==0) { m_usesIntfClassDict = new UsesClassDict(257); } UsesClassDef *ucd=m_usesIntfClassDict->find(cd->name()); if (ucd==0) { ucd = new UsesClassDef(cd); m_usesIntfClassDict->insert(cd->name(),ucd); //printf("in class `%s' adding used intf class `%s'\n", // name().data(),cd->name().data()); } ucd->addAccessor(md->name()); //printf("in class `%s' adding accessor `%s' to class `%s'\n", // name().data(),md->name().data(),ucd->classDef->name().data()); } p=i+l; }}void ClassDef::determineIntfUsageRelation(){ MemberNameInfoSDict::Iterator mnili(*m_allMemberNameInfoList); MemberNameInfo *mni; for (;(mni=mnili.current());++mnili) { MemberNameInfoIterator mnii(*mni); MemberInfo *mi; for (mnii.toFirst();(mi=mnii.current());++mnii) { MemberDef *md=mi->memberDef; // compute the protection level for this member Protection protect=md->protection(); if (mi->prot==Protected) // inherited protection { if (protect==Public) protect=Protected; else if (protect==Protected) protect=Private; } if (!md->name().isEmpty() && md->name()[0]!='@' && (mi->prot!=Private && protect!=Private) ) { // add classes found in the return type addUsedInterfaceClasses(md,md->typeString()); ArgumentList *al = md->argumentList(); if (al) // member has arguments { // add classes found in the types of the argument list ArgumentListIterator ali(*al); Argument *a; for (;(a=ali.current());++ali) { if (!a->type.isEmpty() && a->type.at(0)!='@') { addUsedInterfaceClasses(md,a->type); } } } } } }}#endifPackageDef *ClassDef::packageDef() const{ return m_fileDef ? m_fileDef->packageDef
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -