คำนำหน้าตัวแปร `m_ 'หมายถึงอะไร


155

ฉันมักจะเห็นm_คำนำหน้าใช้สำหรับตัวแปร ( m_World,, m_Sprites... ) ในแบบฝึกหัดตัวอย่างและรหัสอื่น ๆ ที่เกี่ยวข้องกับการพัฒนาเกมเป็นหลัก

เหตุใดผู้คนจึงเพิ่มคำนำหน้าm_ให้กับตัวแปร



18
ก่อนที่จะทำตามคำแนะนำของชาวฮังการีอย่างไร้เหตุผลโปรดตรวจสอบประวัติว่าเป็นสัญกรณ์ฮังการีจริงๆหรือไม่ เพราะการตั้งชื่อ int iCounter นั้นไร้ประโยชน์ แต่การตั้งชื่อ int xAnnotationPos และ yAnnotationPos นั้นสมเหตุสมผล ใช้รุ่นความหมาย
AkselK

บางครั้งคำนำหน้าฟังก์ชั่นโมดูลและตัวแปรที่นำเข้าเพื่อให้คุณมีโอกาสน้อยที่จะเขียนทับพวกเขาด้วยรหัสของคุณเอง มันเป็นวิธีการของชื่อ 'สำรอง' สำหรับการใช้งานเฉพาะ
earthmeLon

3
ในขณะที่ "ฮังการี" สัญกรณ์มักจะดูถูกเหยียดหยามเลวทรามต่ำช้ารสชาติโดยเฉพาะอย่างยิ่งของมันที่หมายถึงขอบเขตตัวแปรจะมีข้อได้เปรียบที่แท้จริงบางอย่าง นอกเหนือจากการระบุขอบเขตของตัวแปรแล้วมันจะป้องกันการชนกันของชื่อเช่นเมื่อโลคอลพาร์กและสมาชิกทุกคนมีเจตนาเดียวกันและด้วยเหตุนี้จึงมีชื่อ "semantic" เดียวกัน สิ่งนี้สามารถทำให้การบำรุงรักษาฐานรหัสขนาดใหญ่ง่ายขึ้นและมีข้อผิดพลาดน้อยลง
เลียน่าสนใจ

8
มีข้อโต้แย้งสำหรับและต่อต้านมาตรฐานการเข้ารหัส แต่คำถามถามอย่างชัดเจนว่าอะไรคืออะไรm_แต่ครึ่งคำตอบที่นี่เป็นคำอธิบายว่าทำไมทุกคนคิดว่าสิ่งที่พวกเขาชื่นชอบในปัจจุบันนั้นดีที่สุด
cz

คำตอบ:


108

นี่คือแบบฝึกหัดการเขียนโปรแกรมทั่วไปสำหรับการกำหนดตัวแปรที่เป็นตัวแปรสมาชิก ดังนั้นเมื่อคุณใช้งานในภายหลังคุณไม่จำเป็นต้องดูว่าพวกเขาถูกกำหนดให้รู้จักขอบเขตของพวกเขาอย่างไร นี่เป็นสิ่งที่ดีถ้าคุณรู้ขอบเขตแล้วและคุณกำลังใช้บางอย่างเช่นintelliSenseคุณสามารถเริ่มต้นด้วยm_และรายการตัวแปรสมาชิกทั้งหมดของคุณจะปรากฏขึ้น เป็นส่วนหนึ่งของสัญกรณ์ฮังการีดูส่วนที่เกี่ยวกับขอบเขตในตัวอย่างที่นี่


51
อาร์กิวเมนต์ที่แย่ที่สุดสำหรับการตั้งชื่อคุณสามารถกด ctrl + space เพื่อ Intellisense
orlp

11
@ nightcracker แม้ว่าฉันไม่ชอบคำนำหน้าเขาหมายถึงว่าเมื่อคุณพิมพ์ m_ แล้วตามด้วย "CTRL + SPACE" (ยกเว้นว่าเป็นอัตโนมัติ) คุณจะได้รับรายการที่มีสมาชิกของคุณเท่านั้น ไม่ใช่เหตุผลที่ดี แต่เป็นข้อดี
Sidar

13
น่าจะพูดถึงว่ามีวิธีมาตรฐานอื่น ๆ อีกมากมายที่จะทำสิ่งเดียวกัน; "m_variable", "m_Variable", "mVariable", "_variable", "_Variable" ... วิธีใดที่ 'ดีที่สุด' หรือ 'ถูกต้อง' (หรือว่าจะทำอะไรเลย) เป็นเรื่องที่ถกเถียงกันและไร้ผลเป็น ' ช่องว่าง vs แท็บ ' :)
Trevor Powell

49
ฉันชอบเพียงแค่ใช้ "this->" - kinda ทำให้ "m_" ซ้ำซ้อนและดียิ่งขึ้นเนื่องจากคอมไพเลอร์บังคับใช้ (ในทางทฤษฎีคุณสามารถป๊อป "m_" กับตัวแปรชนิดใด ๆ ไม่สามารถทำได้ด้วย "this-> ") ส่วนหนึ่งของฉันหวังว่า C ++ จะเป็นมาตรฐานในการทำข้อบังคับ "this->" แต่นั่นจะเข้าสู่โลกแห่งการอภิปรายมากกว่าที่จะเป็นคำตอบ

3
@LaurentCouvidou คุณไม่สามารถจริงๆบังคับ devs ที่สร้างตัวแปรสมาชิกนำหน้าด้วยm_อย่างใดอย่างหนึ่ง
SomeWritesReserved

94

ในรหัสที่สะอาด: คู่มือของงานฝีมือซอฟต์แวร์เปรียวมีคำแนะนำที่ชัดเจนกับการใช้คำนำหน้านี้:

คุณไม่จำเป็นต้องใส่คำนำหน้าตัวแปรสมาชิกด้วยm_อีกต่อไป คลาสและฟังก์ชั่นของคุณควรเล็กพอที่คุณไม่ต้องการ

นอกจากนี้ยังมีตัวอย่าง (รหัส C #) ของสิ่งนี้:

การปฏิบัติที่ไม่ดี:

public class Part
{
    private String m_dsc; // The textual description

    void SetName(string name)
    {
        m_dsc = name;
    }
}

แนวปฏิบัติที่ดี:

public class Part
{
    private String description;

    void SetDescription(string description)
    {
        this.description = description;
    }
}

เรานับกับโครงสร้างภาษาที่จะอ้างถึงตัวแปรสมาชิกในกรณีของความคลุมเครืออย่างชัดเจน (คนคือ , descriptionสมาชิกและพารามิเตอร์):descriptionthis


6
ข้อความอาจเป็น "มีคำแนะนำที่ชัดเจนต่อต้านการใช้คำนำหน้านี้:"
Xofo

ฉันดีใจที่มีคนเขียนมัน
dmitreyg

อีกเหตุผลหนึ่งคือใน java getter / setter ถือว่าเป็น getName / setName ดังนั้น getM_name จึงไม่ดีและคุณต้องจัดการทีละตัว
Leon

ขอขอบคุณที่เขียนสิ่งนี้ ฉันแค่อยากจะชี้ให้เห็นว่าหนังสือที่คุณอ้างมานั้นมีมาตั้งแต่เดือนสิงหาคม 2008 และฉันยังคงพบข้อปฏิบัติที่ไม่ดีนี้ในรหัสใหม่วันนี้ (2019)
alexlomba87

20

มันเป็นเรื่องธรรมดาใน C ++ นี่เป็นเพราะใน C ++ คุณไม่สามารถมีชื่อเดียวกันสำหรับฟังก์ชันสมาชิกและตัวแปรสมาชิกและฟังก์ชัน getter มักตั้งชื่อโดยไม่มีคำนำหน้า "รับ"

class Person
{
   public:
      std::string name() const;

   private:
      std::string name; // This would lead to a compilation error.
      std::string m_name; // OK.
};

main.cpp:9:19: error: duplicate member 'name'
      std::string name;
                  ^
main.cpp:6:19: note: previous declaration is here
      std::string name() const;
                  ^
1 error generated.

http://coliru.stacked-crooked.com/a/f38e7dbb047687ad

"m_" ระบุสำหรับ "สมาชิก" คำนำหน้า "_" ก็เหมือนกัน

คุณไม่ควรใช้มันในภาษาการเขียนโปรแกรมที่แก้ปัญหานี้โดยใช้อนุสัญญา / ไวยากรณ์ที่แตกต่างกัน


11

m_คำนำหน้ามักจะใช้สำหรับตัวแปรสมาชิก - ฉันคิดว่าประโยชน์หลักของมันคือว่ามันจะช่วยสร้างความแตกต่างที่ชัดเจนระหว่างทรัพย์สินของประชาชนและภาคเอกชนตัวแปรสมาชิกสนับสนุนมัน

int m_something

public int Something => this.m_something; 

มันสามารถช่วยให้มีหลักการตั้งชื่อที่สอดคล้องกันสำหรับการสำรองตัวแปรและm_คำนำหน้าเป็นวิธีหนึ่งในการทำเช่นนั้น - สิ่งหนึ่งที่ทำงานในภาษาที่ไม่คำนึงถึงขนาดตัวพิมพ์

สิ่งนี้มีประโยชน์อย่างไรขึ้นอยู่กับภาษาและเครื่องมือที่คุณใช้ IDEs ที่ทันสมัยพร้อมด้วยเครื่องมือ refactor ที่แข็งแกร่งและ intellisense ต้องการน้อยกว่าสำหรับการประชุมเช่นนี้และแน่นอนว่าไม่ใช่วิธีเดียวในการทำเช่นนี้ แต่ก็คุ้มค่าที่จะได้รับการฝึกฝนในทุกกรณี


5
หากคุณต้องเขียนthis.ด้วยภาษาของคุณก็m_ไม่มีประโยชน์จริงๆ
Ruslan

@Ruslan m_คือการแยกความแตกต่างจากคุณสมบัติมันหลัง - ดังนั้นthis.Somethingสำหรับคุณสมบัติเทียบthis.m_somethingกับสมาชิกสำรอง มันไม่ใช่แบบแผนที่ฉันชอบ แต่ฉันเห็นว่าส่วนใหญ่ใช้ในกรณีที่ไม่มีความรู้สึกภาษา (เช่น VB)
Keith

1
ทำไมไม่this.Somethingสำหรับคุณสมบัติและthis.somethingการสำรองข้อมูล หรือthis._somethingสำหรับการสนับสนุน? this.m_somethingซ้ำซ้อน ฉันใช้_somethingเพื่อที่ฉันไม่ได้ตั้งใจพิมพ์เมื่อฉันไปพิมพ์Somethingไม่มีอะไรจะทำอย่างไรกับ membershipness หรือไม่
AustinWBryan

@AustinWBryan ดูความคิดเห็นก่อนหน้าของฉันเกี่ยวกับภาษาที่ไม่ตรงตามตัวพิมพ์ใหญ่ - เล็ก ใช่_คำนำหน้าของมันจะทำงาน แต่m_เป็นแบบแผน ไม่ใช่สิ่งที่ฉันจะใช้เป็นการส่วนตัว แต่ถ้าคุณเห็นในโค้ดที่เป็นเจตนาของผู้เขียน
Keith

7

ดังที่ระบุไว้ในคำตอบอื่น ๆm_คำนำหน้าใช้เพื่อระบุว่าตัวแปรเป็นสมาชิกคลาส สิ่งนี้แตกต่างจากสัญกรณ์ฮังการีเนื่องจากไม่ได้ระบุประเภทของตัวแปร แต่เป็นบริบท

ฉันใช้m_ใน C ++ แต่ไม่ใช่ในภาษาอื่นที่มี 'บังคับ' หรือ 'ตัวเอง' ฉันไม่ชอบที่จะเห็น 'this->' ที่ใช้กับ C ++ เพราะมันเป็นตัวตัดรหัส

คำตอบm_dscก็คือ "การปฏิบัติที่ไม่ดี" และ "คำอธิบาย" คือ "การปฏิบัติที่ดี" แต่นี่เป็นปลาเฮอริ่งแดงเนื่องจากปัญหามีตัวย่อ

คำตอบอีกข้อหนึ่งคือการพิมพ์thisป๊อปอัป IntelliSense แต่ IDE ที่ดีจะมีฮ็อตคีย์เพื่อป๊อปอัป IntelliSense สำหรับสมาชิกชั้นปัจจุบัน


"แต่นี่คือปลาเฮอริ่งแดง" - จุดดี การเปรียบเทียบยุติธรรมจะเทียบm_description description
ต่อสู้

3

ตามที่ระบุไว้ในการตอบสนองอื่น ๆ m_ เป็นคำนำหน้าที่หมายถึงตัวแปรสมาชิก มัน / ถูกใช้กันทั่วไปในโลก C ++ และเผยแพร่ไปยังภาษาอื่นเช่นกันรวมถึง Java

ใน IDE ที่ทันสมัยมันจะซ้ำซ้อนสมบูรณ์เน้นไวยากรณ์ที่ทำให้มันเห็นได้ชัดซึ่งตัวแปรท้องถิ่นและคนที่เป็นสมาชิก อย่างไรก็ตามด้วยการเน้นไวยากรณ์เวลาปรากฏในปลาย 90s การประชุมได้รอบหลายปีและถูกกำหนดอย่างแน่นหนา (อย่างน้อยในโลก C ++)

ฉันไม่รู้ว่าคุณกำลังอ้างถึงบทเรียนใด แต่ฉันจะเดาว่าพวกเขากำลังใช้การประชุมเนื่องจากหนึ่งในสองปัจจัย:

  • พวกเขาเป็นแบบฝึกหัด C ++ ที่เขียนโดยคนที่ใช้ในการประชุม m_ และ / หรือ ...
  • พวกเขาเขียนรหัสในข้อความธรรมดา (monospaced) โดยไม่มีการเน้นไวยากรณ์ดังนั้นการประชุม m_ มีประโยชน์ในการทำให้ตัวอย่างชัดเจนขึ้น

ตัวอย่างหนึ่งอาจเป็นเช่นนี้: wiki.qt.io/How_to_Use_QSettings เนื่องจาก Qt Creator IS ใช้การเน้นการเดาครั้งแรกอาจปรากฏขึ้น ข้อแตกต่างเล็กน้อยอาจเป็นอีกรูปแบบหนึ่งที่ใช้ _object () สำหรับวัตถุส่วนตัวของคลาสและ p_variable ถ้ามันเป็นตัวชี้เนื่องจากทั้งคู่ไม่ได้เป็น highligted อย่างที่ฉันรู้และดูเหมือนสมเหตุสมผลสำหรับฉันที่จะใช้มัน
Ivanovic

3

Lockheed Martin ใช้รูปแบบการตั้งชื่อ 3 คำนำหน้าซึ่งยอดเยี่ยมในการใช้งานโดยเฉพาะอย่างยิ่งเมื่ออ่านรหัสของผู้อื่น

   Scope          Reference Type(*Case-by-Case)   Type

   member   m     pointer p                       integer n
   argument a     reference r                     short   n
   local    l                                     float   f
                                                  double  f
                                                  boolean b

ดังนั้น...

int A::methodCall(float af_Argument1, int* apn_Arg2)
{
    lpn_Temp = apn_Arg2;
    mpf_Oops = lpn_Temp;  // Here I can see I made a mistake, I should not assign an int* to a float*
}

รับไปเพื่อสิ่งที่คุ้มค่า


น่ากลัว ขอบคุณสำหรับ "ตัวอย่าง" จุดที่มีประโยชน์จริงๆคือเมื่อคุณแก้ไขโค้ด 200,000 บรรทัด
jiveturkey

1
ไม่จำเป็นต้องได้รับการป้องกัน ฉันพยายามช่วยคุณด้วยการแสดงให้คุณเห็นว่ามีคำตอบที่ผิดพลาด ให้ฉันมีความชัดเจนมากขึ้นแล้ว: ไม่สำคัญว่าคุณมีรหัส 5 หรือ 200000 บรรทัด: คอมไพเลอร์จะไม่อนุญาตให้คุณทำงานที่ได้รับมอบหมายด้วยตัวชี้ประเภทที่เข้ากันไม่ได้ ดังนั้นจุดที่ทำไว้ในความคิดเห็นก็คือ moot
Cássio Renan

ไม่ได้หมายความว่าจะหลุดออกมาเป็นการป้องกัน ขอโทษ
jiveturkey

มันเป็นรูปแบบของสัญกรณ์ฮังการีซึ่งไม่ได้ทำให้ความรู้สึกในภาษาที่ทันสมัย ...
doc

2

เพื่อให้คำตอบในปัจจุบันเสร็จสมบูรณ์และเนื่องจากคำถามไม่ได้เป็นภาษาที่เฉพาะเจาะจงโครงการ C บางโครงการใช้คำนำหน้าm_เพื่อกำหนดตัวแปรทั่วโลกที่เฉพาะเจาะจงกับไฟล์ - และg_สำหรับตัวแปรทั่วโลกที่มีขอบเขตที่ใหญ่กว่าไฟล์ที่กำหนดไว้
ในกรณีนี้ตัวแปรที่กำหนดไว้ด้วยคำนำหน้าควรจะกำหนดให้เป็นm_ static

ดูข้อตกลงการเข้ารหัส EDK2 (การประยุกต์ใช้ UEFI โอเพนซอร์ซ)สำหรับตัวอย่างโครงการโดยใช้ระเบียบนี้


1

ข้อโต้แย้งหนึ่งที่ฉันยังไม่เห็นคือคำนำหน้าเช่นm_สามารถใช้เพื่อป้องกันการปะทะกันของชื่อด้วย#defineแมโครของ d

Regex ค้นหาจาก#define [a-z][A-Za-z0-9_]*[^(]ใน/usr/include/term.hจาก curses / ncurses

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.