📄 tools.htm
字号:
TAG TAG; CLASS CL; // DON'T WANT TO CHECK INSTANCES. THE !TAG.CLASSTYPE(CL) CALL ALSO REJECTS ENUMS. IF (!SYM.SYMBOLTOTAG(TAG) || !TAG.CLASSTYPE(CL) || IS_INSTANTIATED(CL.ATTRIB())) RETURN; // REJECT STRUCTS AND UNIONS, WHICH ARE ALSO REPRESENTED AS CLASSES. IF (WAS_STRUCT(CL.ATTRIB()) || WAS_UNION(CL.ATTRIB())) RETURN; // GET POSSIBLE BASE CLASSES AND DERIVED CLASSES. ATTRIBUTE_ITERATOR(TAG) BCL=CL.BASECLASSES(); ATTRIBUTE_ITERATOR(TAG) DCL=CL.DERIVEDCLASSES(); // REJECT DERIVED CLASSES. ITERATE_BEGIN(BCL) { RETURN; } ITERATE_END(BCL); // CHECK ONLY BASE CLASSES. ITERATE_BEGIN(DCL) { FUNCTIONMEMBER FM; CHAR DTOR_NAME[256]; CHAR MSG[1024]; // DESTRUCTORS CAN BE IDENTIFIED BY THEIR NAME. STRCPY(DTOR_NAME, TAG.NAME()); STRCAT(DTOR_NAME, "::~"); STRCAT(DTOR_NAME, TAG.NAME()); STRCAT(DTOR_NAME, "()"); // BASE CLASS MUST DECLARE A DESTRUCTOR MEMBER FUNCTION THAT IS VIRTUAL. IF (CL.FINDFUNCTIONMEMBER(DTOR_NAME, FM) IS_VIRTUAL(FM.ATTRIB())) { RETURN; } // ISSUE THE VIOLATION MESSAGE. SPRINTF(MSG, "BASECLASS '%S' SHOULD DECLARE A VIRTUAL DESTRUCTOR", TAG.NAME()); VIOLATION(TAG, MSG); RETURN; } ITERATE_END(DCL); } // RETURNS A ONE-LINE SUMMARY OF THE VIOLATION WITH NO INSTANCE-SPECIFIC INFORMATION. CONST CHAR *RULE_VIRTDTORINBASECLASS::ERRORMESS() CONST { RETURN("BASE CLASS MUST DECLARE A VIRTUAL DESTRUCTOR."); } // RETURNS THE NAME OF THIS RULE. CONST CHAR *RULE_VIRTDTORINBASECLASS::NAME() CONST { RETURN("RULE_VIRTDTORINBASECLASS"); } STATIC RULE_VIRTDTORINBASECLASS INSTANCE;Finally, here's Rule 10 in the constraint expression language CenterLine plans to release in an upcoming version of AcquaProva. This code was provided by CenterLine: advBool advSMNonvirtualDestructor::DoesEntityViolateRule (const advClassStructOrUnionTypet, advDiagnosticd) const { advBool result = adv_false; do { if (t.HasBaseClasses() t.HasDestructor()) { if (t.Destructor()->IsCompilerGenerated()) { d << "Class type:" << t << "Base classes without virtual destructors:"; // Make sure that all direct // bases have virtual destructors. (There's no need to check // indirect bases since they will have been checked previously.) class CheckForBaseClassesWithNonvirtualDestructors : public advForEachFunction<advClassStructOrUnionType::BaseClassInfo> { public: CheckForBaseClassesWithNonvirtualDestructors(advDiagnosticd, advBoolresult) : d_(d), result_(result) {} virtual void operator()(const advClassStructOrUnionType::BaseClassInfob, advBool{ if (!b.base_class_.HasDestructor() || !b.base_class_.Destructor()->IsVirtual()) { // A base class with a non-virtual destructor! result_ = adv_true; // Add the offending base class to the diagnostic so that // the user will know what was wrong. d_ << b.base_class_; } // if } private: advDiagnosticd_; advBoolresult_; } check_for_base_classes_with_nonvirtual_destructors(d, result); (void) t.ForEachBaseClass (check_for_base_classes_with_nonvirtual_destructors); } // if } while (adv_false); return result; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -