Tiền tố biến `m_` có nghĩa là gì?


154

Tôi thường thấy m_tiền tố được sử dụng cho các biến ( m_World,, m_Sprites...) trong hướng dẫn, ví dụ và mã khác chủ yếu liên quan đến phát triển trò chơi.

Tại sao mọi người thêm tiền tố m_vào các biến?



18
Trước khi vô tư làm theo phù hợp với ký hiệu của Lynn, xin vui lòng kiểm tra lịch sử về ký hiệu Hungary thực sự là gì. Bởi vì việc đặt tên int iCount chỉ là vô nghĩa. Nhưng đặt tên int xAnnotationPos và yAnnotationPos là hợp lý. Sử dụng phiên bản Semantic.
AkselK

Đôi khi, các mô-đun nhập các hàm tiền tố và các biến để bạn ít có khả năng ghi đè chúng bằng mã của riêng bạn. Đó là một cách 'đặt trước' tên cho một mục đích sử dụng cụ thể.
earthmeLon

3
Trong khi ký hiệu "Hungary" thường bị chế giễu, thì hương vị đặc biệt của nó biểu thị phạm vi biến có một số lợi thế thực sự. Ngoài việc xác định phạm vi của biến, nó còn ngăn chặn các xung đột tên, vì khi một địa phương, một nhóm và một thành viên đều có cùng một mục đích và do đó có cùng tên "ngữ nghĩa". Điều này có thể làm cho việc bảo trì các cơ sở mã lớn đơn giản hơn và ít bị lỗi hơn.
Hot Licks

8
Có những lập luận cho và chống lại bất kỳ tiêu chuẩn mã hóa nào, nhưng câu hỏi rõ ràng là hỏi cái gì m_, nhưng một nửa câu trả lời ở đây là một bình luận về lý do tại sao mọi người nghĩ rằng yêu thích hiện tại của họ là tốt nhất.
cz

Câu trả lời:


108

Đây là thực hành lập trình điển hình để xác định các biến là biến thành viên. Vì vậy, khi bạn sử dụng chúng sau này, bạn không cần phải xem chúng được xác định ở đâu để biết phạm vi của chúng. Điều này cũng tuyệt vời nếu bạn đã biết phạm vi và bạn đang sử dụng một cái gì đó như intelliSense , bạn có thể bắt đầu với m_và một danh sách tất cả các biến thành viên của bạn được hiển thị. Một phần của ký hiệu Hungary, xem phần về phạm vi trong các ví dụ ở đây .


51
Đối số tồi tệ nhất cho một quy ước đặt tên bao giờ hết, bạn chỉ cần nhấn ctrl + dấu cách cho intellisense.
orlp

11
@nightcracker mặc dù tôi không thích tiền tố, anh ta có nghĩa là nói rằng khi bạn nhập m_ và sau đó "CTRL + SPACE" (trừ khi nó tự động), bạn sẽ nhận được một danh sách chỉ chứa các thành viên của bạn. Không hẳn là một lý do chính đáng nhưng đó là một lợi thế.
Sidar

13
Đáng nói là có rất nhiều cách tiêu chuẩn khác ít nhiều để làm điều tương tự; "m_variable", "m_Variable", "mVariable", "_variable", "_Variable" ... cách nào là 'tốt nhất' hoặc 'đúng' (hoặc liệu có nên làm điều đó không gây tranh cãi và không có kết quả như ' dấu cách so với tab '. :)
Trevor Powell

49
Tôi thích chỉ sử dụng "this->" - kinda làm cho "m_" trở nên dư thừa và thậm chí còn tốt hơn khi nó được trình biên dịch thực thi (theo lý thuyết bạn có thể bật "m_" trên bất kỳ loại biến nào; không thể làm điều đó với "this-> "). Một phần trong tôi mong muốn C ++ sẽ chuẩn hóa việc đưa ra "điều này->" bắt buộc. Nhưng đó là đi sâu vào thế giới thảo luận hơn là một câu trả lời.

3
@LaurentCouvidou, bạn thực sự không thể thực thi rằng các nhà phát triển tạo các biến thành viên có tiền tố m_.
Một số trang được ghi nhận vào

94

Trong Clean Code: Cẩm nang về thủ công phần mềm linh hoạt, có một khuyến nghị rõ ràng chống lại việc sử dụng tiền tố này:

Bạn cũng không cần phải thêm tiền tố vào các biến thành viên m_nữa. Các lớp học và chức năng của bạn phải đủ nhỏ để bạn không cần đến chúng.

Ngoài ra còn có một ví dụ (mã C #) về điều này:

Thực hành xấu:

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

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

Thực hành tốt:

public class Part
{
    private String description;

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

Chúng tôi tính với cấu trúc ngôn ngữ để tham khảo các biến thành viên trong trường hợp rõ ràng mập mờ ( ví dụ , descriptionthành viên và descriptiontham số): this.


6
Từ ngữ có thể là "có một khuyến nghị rõ ràng CHỐNG LẠI việc sử dụng tiền tố này:"
Xofo

Tôi rất vui vì ai đó đã viết nó
dmitreyg

Một lý do khác là trong java getter / setter được coi là getName / setName, vì vậy getM_name rất tệ và bạn cần xử lý từng cái một.
Leon

Cảm ơn đã viết bài này. Tôi chỉ muốn chỉ ra rằng cuốn sách bạn trích dẫn đã được phát hành từ tháng 8 năm 2008 - và tôi vẫn thấy thực tiễn tồi tệ này trong mã mới ngày hôm nay (2019).
alexlomba87

20

Đó là thực tế phổ biến trong C ++. Điều này là do trong C ++, bạn không thể có cùng tên cho hàm thành viên và biến thành viên và các hàm getter thường được đặt tên mà không có tiền tố "get".

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-crooking.com/a/f38e7dbb047687ad

"m_" trạng thái cho "thành viên". Tiền tố "_" cũng phổ biến.

Bạn không nên sử dụng nó trong các ngôn ngữ lập trình giải quyết vấn đề này bằng cách sử dụng các quy ước / ngữ pháp khác nhau.


11

Các m_tiền tố thường được sử dụng cho các biến thành viên - Tôi nghĩ lợi thế chính của nó là nó giúp tạo ra một sự phân biệt rõ ràng giữa một tài sản công cộng và tư nhân biến thành viên ủng hộ nó:

int m_something

public int Something => this.m_something; 

Nó có thể giúp có một quy ước đặt tên nhất quán cho các biến sao lưu và m_ tiền tố là một cách để làm điều đó - một cách hoạt động trong các ngôn ngữ không phân biệt chữ hoa chữ thường.

Điều này hữu ích như thế nào tùy thuộc vào ngôn ngữ và công cụ bạn đang sử dụng. Các IDE hiện đại với các công cụ tái cấu trúc mạnh và intellisense ít cần các quy ước như thế này và chắc chắn đó không phải là cách duy nhất để làm điều này, nhưng nó đáng để nhận thức về thực tiễn trong mọi trường hợp.


5
Nếu bạn phải viết this.bằng ngôn ngữ của bạn, thì m_thực sự vô dụng.
Ruslan

@Ruslan m_là để phân biệt nó với tài sản mà nó ủng hộ - vì vậy this.Somethingđối với tài sản so this.m_somethingvới thành viên ủng hộ. Đó không phải là một quy ước tôi thích bản thân mình, nhưng tôi hầu như đã thấy nó được sử dụng trong trường hợp ngôn ngữ không nhạy cảm (như VB).
Keith

1
Tại sao không, this.Somethingcho tài sản và this.somethingcho sự ủng hộ? Hoặc this._somethingcho sự ủng hộ? this.m_somethinglà dư thừa. Tôi sử dụng _somethingđể tôi không vô tình gõ nó khi tôi nhập Something, không liên quan gì đến tư cách thành viên hay không
AustinWBryan

@AustinWBryan xem nhận xét trước đây của tôi về các ngôn ngữ không phân biệt chữ hoa chữ thường. Vâng, một _tiền tố trên chính nó sẽ thực hiện công việc, nhưng m_là quy ước. Đó không phải là cái mà tôi sử dụng cá nhân, nhưng nếu bạn thấy nó trong mã đó là ý định của tác giả.
Keith

7

Như đã nêu trong các câu trả lời khác, m_ tiền tố được sử dụng để chỉ ra rằng một biến là một thành viên lớp. Điều này khác với ký hiệu Hungary vì nó không chỉ ra loại biến mà là bối cảnh của nó.

Tôi sử dụng m_trong C ++ nhưng không phải trong một số ngôn ngữ khác trong đó 'cái này' hoặc 'cái tôi' là bắt buộc. Tôi không muốn thấy 'this->' được sử dụng với C ++ vì nó làm xáo trộn mã.

Một câu trả lời khác nói m_dsclà "thực hành xấu" và 'mô tả;' là "thực hành tốt" nhưng đây là cá trích đỏ vì vấn đề là viết tắt.

Một câu trả lời khác nói rằng việc gõ thisbật lên IntelliSense nhưng bất kỳ IDE tốt nào cũng sẽ có một phím nóng để bật lên IntelliSense cho các thành viên lớp hiện tại.


"nhưng đây là cá trích đỏ" - Điểm hay. Một so sánh công bằng sẽ là m_descriptionvs description.
Trận chiến

3

Như đã nêu trong nhiều phản hồi khác, m_ là tiền tố biểu thị các biến thành viên. Nó được / thường được sử dụng trong thế giới C ++ và được truyền bá sang các ngôn ngữ khác, bao gồm cả Java.

Trong một IDE hiện đại, nó hoàn toàn dư thừa vì việc tô sáng cú pháp làm cho nó rõ ràng biến nào là cục bộ và biến nào là thành viên . Tuy nhiên, bằng cách đánh dấu cú pháp thời gian xuất hiện vào cuối những năm 90, quy ước đã tồn tại trong nhiều năm và được thiết lập vững chắc (ít nhất là trong thế giới C ++).

Tôi không biết bạn đang đề cập đến hướng dẫn nào, nhưng tôi sẽ đoán rằng họ đang sử dụng quy ước do một trong hai yếu tố:

  • Chúng là các hướng dẫn về C ++, được viết bởi những người được sử dụng cho quy ước m_ và / hoặc ...
  • Họ viết mã bằng văn bản thuần túy (đơn cách), không có tô sáng cú pháp, vì vậy quy ước m_ rất hữu ích để làm cho các ví dụ rõ ràng hơn.

Một ví dụ có thể là: wiki.qt.io/How_to_Use_QSinstall Vì Qt Creator IS sử dụng tô sáng, lần đoán đầu tiên có thể xuất hiện. Một chút khác biệt có thể là một quy ước khác khi sử dụng _object () cho các đối tượng riêng của một lớp và p_variable nếu nó là một con trỏ vì cả hai đều không được đánh dấu như tôi biết và dường như có ý nghĩa đối với tôi khi sử dụng nó.
Ivanovic

3

Lockheed Martin sử dụng sơ đồ đặt tên 3 tiền tố rất tuyệt vời để làm việc, đặc biệt là khi đọc mã của người khác.

   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

Vì thế...

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*
}

Mang nó cho những gì nó có giá trị.


Tuyệt vời. Cảm ơn vì "ví dụ". Nơi nó thực sự có ích là khi bạn chỉnh sửa 200.000 dòng mã.
jiveturkey

1
Không cần phải phòng thủ. Tôi thành thật đang cố gắng giúp bạn bằng cách cho bạn thấy rằng có một lỗi trong câu trả lời của bạn. Để tôi nói rõ hơn, sau đó: Không thành vấn đề nếu bạn có 5 hoặc 200000 dòng mã: Trình biên dịch sẽ không cho phép bạn thực hiện một bài tập với các loại con trỏ không tương thích. Vì vậy, điểm được thực hiện trong các bình luận là moot.
Cássio Renan

Không có nghĩa là đi ra như phòng thủ. Lấy làm tiếc.
jiveturkey

Đó là một biến thể của ký hiệu Hungary, không có ý nghĩa trong các ngôn ngữ hiện đại ...
doc

2

Để hoàn thành các câu trả lời hiện tại và vì câu hỏi không phải là ngôn ngữ cụ thể, một số dự án C sử dụng tiền tố m_để xác định các biến toàn cục dành riêng cho một tệp - và g_cho các biến toàn cục có phạm vi lớn hơn tệp được xác định.
Trong trường hợp này, các biến toàn cục được xác định bằng tiền tố m_ phải được xác định là static.

Xem quy ước mã hóa EDK2 (một triển khai mã nguồn mở UEFI) để biết ví dụ về dự án sử dụng quy ước này.


1

Một đối số mà tôi chưa từng thấy là một tiền tố như m_có thể được sử dụng để ngăn chặn xung đột tên với #define'd macro'.

Regex tìm kiếm #define [a-z][A-Za-z0-9_]*[^(]trong /usr/include/term.hnhững lời nguyền / ncurses.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.