คำอธิบายหลายประการ อันแรกเป็นแบบทั่วไปอันที่สองเฉพาะสำหรับมาโครตัวประมวลผลล่วงหน้า C ที่มีพารามิเตอร์:
การควบคุมการไหล
ฉันเคยเห็นสิ่งนี้ใช้ในรหัส C ธรรมดา โดยพื้นฐานแล้วมันเป็น goto เวอร์ชันที่ปลอดภัยกว่าเนื่องจากคุณสามารถแยกออกได้และหน่วยความจำทั้งหมดจะได้รับการทำความสะอาดอย่างเหมาะสม
ทำไมบางสิ่งบางอย่างถึงgoto
ดี? ถ้าคุณมีโค้ดที่เกือบทุกบรรทัดสามารถส่งคืนข้อผิดพลาดได้ แต่คุณต้องตอบสนองต่อทั้งหมดในลักษณะเดียวกัน (เช่นโดยการส่งข้อผิดพลาดไปยังผู้โทรของคุณหลังจากล้างข้อมูล) โดยปกติแล้วจะสามารถอ่านได้มากกว่าเพื่อหลีกเลี่ยงif( error ) { /* cleanup and error string generation and return here */ }
as หลีกเลี่ยงการทำซ้ำรหัสการล้างข้อมูล
อย่างไรก็ตามใน C ++ คุณมีข้อยกเว้น + RAII สำหรับจุดประสงค์นี้ดังนั้นฉันคิดว่ารูปแบบการเข้ารหัสไม่ดี
การตรวจสอบอัฒภาค
หากคุณลืมเครื่องหมายอัฒภาคหลังจากการเรียกใช้แมโครที่เหมือนฟังก์ชันอาร์กิวเมนต์อาจหดตัวในลักษณะที่ไม่ต้องการและรวบรวมเป็นไวยากรณ์ที่ถูกต้อง ลองนึกภาพมาโคร
#define PRINT_IF_DEBUGMODE_ON(msg) if( gDebugModeOn ) printf("foo");
ที่เรียกโดยบังเอิญว่าเป็น
if( foo )
PRINT_IF_DEBUGMODE_ON("Hullo\n")
else
doSomethingElse();
"else" จะถูกพิจารณาว่ามีความเกี่ยวข้องgDebugModeOn
ดังนั้นเมื่อfoo
ใดfalse
ที่การย้อนกลับที่แน่นอนของสิ่งที่ตั้งใจไว้จะเกิดขึ้น
กำหนดขอบเขตสำหรับตัวแปรชั่วคราว
เนื่องจาก do / while มีวงเล็บปีกกาตัวแปรชั่วคราวจึงมีขอบเขตที่กำหนดไว้อย่างชัดเจนจึงไม่สามารถหลีกเลี่ยงได้
หลีกเลี่ยงคำเตือน "อัฒภาคที่อาจไม่ต้องการ"
มาโครบางตัวเปิดใช้งานเฉพาะในรุ่นแก้จุดบกพร่องเท่านั้น คุณกำหนดพวกเขาเช่น:
#if DEBUG
#define DBG_PRINT_NUM(n) printf("%d\n",n);
#else
#define DBG_PRINT_NUM(n)
#endif
ตอนนี้ถ้าคุณใช้สิ่งนี้ในรีลีสบิลด์ภายในเงื่อนไขจะคอมไพล์
if( foo )
;
คอมไพเลอร์หลายคนเห็นว่าสิ่งนี้เหมือนกับไฟล์
if( foo );
ซึ่งมักเขียนโดยบังเอิญ. คุณจึงได้รับคำเตือน do {} while (false) ซ่อนสิ่งนี้จากคอมไพลเลอร์และได้รับการยอมรับว่าเป็นสิ่งที่บ่งบอกว่าคุณไม่ต้องการทำอะไรเลยที่นี่
การหลีกเลี่ยงการจับเส้นตามเงื่อนไข
มาโครจากตัวอย่างก่อนหน้านี้:
if( foo )
DBG_PRINT_NUM(42)
doSomething();
ตอนนี้ในการสร้างการดีบักเนื่องจากเรารวมอัฒภาคเป็นนิสัยการคอมไพล์นี้ใช้ได้ดี อย่างไรก็ตามในการสร้างรุ่นนี้จะกลายเป็น:
if( foo )
doSomething();
หรือจัดรูปแบบให้ชัดเจนยิ่งขึ้น
if( foo )
doSomething();
ซึ่งไม่ใช่สิ่งที่ตั้งใจไว้เลย การเพิ่ม do {... } ในขณะที่ (false) รอบ ๆ มาโครจะเปลี่ยนอัฒภาคที่หายไปให้เป็นข้อผิดพลาดในการคอมไพล์
นั่นหมายความว่าอย่างไรสำหรับ OP?
โดยทั่วไปคุณต้องการใช้ข้อยกเว้นใน C ++ สำหรับการจัดการข้อผิดพลาดและเทมเพลตแทนมาโคร อย่างไรก็ตามในกรณีที่หายากมากที่คุณยังต้องการมาโคร (เช่นเมื่อสร้างชื่อคลาสโดยใช้การวางโทเค็น) หรือ จำกัด ไว้ที่ C ธรรมดานี่เป็นรูปแบบที่มีประโยชน์