Có một quy ước viết hoa phổ biến trong C ++? [đóng cửa]


13

Tôi làm rất nhiều công việc trong Python và Java và cả hai ngôn ngữ này đều có các quy ước khá phổ biến (mặc dù không phổ biến) về cách sử dụng viết hoa trong các định danh: cả hai đều sử dụng PascalCasecho tên lớp và ALL_CAPScho các hằng số "toàn cầu", nhưng cho các định danh khác rất nhiều mã Java sử dụng mixedCasetrong khi rất nhiều mã Python sử dụng underscore_delimiters. Tôi biết rằng không có ngôn ngữ hoặc thư viện nào thực thi bất kỳ chữ viết hoa cụ thể nào, nhưng tôi đã thấy rằng khi tôi tuân theo các quy ước tiêu chuẩn cho ngôn ngữ tôi đang sử dụng, mã của tôi có vẻ dễ đọc hơn nhiều.

Bây giờ tôi đang bắt đầu một dự án trong C ++ và tôi muốn áp dụng ý tưởng tương tự. Có bất kỳ quy ước phổ biến nhất cho viết hoa mà tôi nên biết về?


Vấn đề với camelCase là nó không chơi tốt với bộ tiền xử lý. Không phải là một vấn đề lớn, đặc biệt là vì bộ tiền xử lý thường có thể tránh được.
Pubby

Tôi đã phải đối mặt với quyết định này chỉ một vài ngày trước. Cuối cùng, nó là một thứ không có trí tuệ, vì cả thư viện tiêu chuẩn và boost đều sử dụng underscore_lowercase_d Friiter. Vì tôi sử dụng boost như một booster STL, nó sẽ được rắc toàn bộ về mã của tôi. Các thư viện khác mà tôi sử dụng là PascalCase (SFML) có thể dễ dàng được chứa hơn nên bất kỳ phương thức đã cho nào cũng khá chuẩn.
Tối đa

@ Pubby8: vì tò mò: làm thế nào để camelCase đụng độ với bộ tiền xử lý?
Joachim Sauer

@JoachimSauer Các từ riêng lẻ trong camelCase có thể có trường hợp khác, nhưng macro không thể thay đổi trường hợp. Điều này trở thành một vấn đề nếu bạn muốn một macro lấy một phần của từ làm đối số - bạn có thể phải cung cấp cả hai trường hợp dưới dạng đối số: macro (x, X). Đây là một vấn đề nhỏ, nhưng nên biết nếu bạn có ý định sử dụng bộ tiền xử lý.
Pubby

Câu trả lời:


27

Có bất kỳ quy ước phổ biến nhất cho viết hoa mà tôi nên biết về?

C ++ dựa trên C, đã đủ tuổi để phát triển một loạt các quy ước đặt tên cho đến khi C ++ được phát minh. Sau đó, C ++ đã thêm một vài cái và C cũng không nhàn rỗi khi nghĩ đến cái mới. Thêm vào đó, nhiều ngôn ngữ có nguồn gốc C, đã phát triển các quy ước đặt tên C của nhà phát minh của họ hơn nữa, đến mức họ thụ tinh lại trên C và C ++ ... Nói cách khác: C ++ không phải là một, nhưng nhiều quy ước như vậy.

Tuy nhiên, nếu bạn đang tìm kiếm một quy ước đặt tên, bạn cũng có thể xem quy ước đặt tên của thư viện chuẩn , bởi vì đây là quy ước duy nhất mà tất cả các nhà phát triển C ++ sẽ phải biết và sử dụng.

Tuy nhiên, bất cứ điều gì bạn sử dụng quy tắc quan trọng nhất là: Hãy nhất quán!

Thật thú vị, trong khi tôi bắt đầu với sự pha trộn giữa PascalCase và camelCase, và đã tham gia vào nhiều dự án với nhiều quy ước đặt tên hơn, qua nhiều năm, tôi thấy tôi ngày càng bị mắc kẹt với tiêu chuẩn_l thư viện_con tắc. Đừng hỏi tôi tại sao.


Cảm ơn thông tin ... vậy thư viện tiêu chuẩn là dấu gạch dưới, sau đó? (ít nhất là nhiều hơn bất cứ thứ gì khác?) Tôi đã suy nghĩ theo những dòng đó, nhưng thật khó để nói vì những thứ như iostream trong đó một nửa tên phương thức dường như là cùng một đoạn từ ghép với nhau như ANSI C :-P
David Z

5
@David: Thư viện iostreams có lẽ 25 tuổi và (ngoại trừ C lib, hoặc khóa học) có thể là phần cũ nhất của lib C ++ std lib. Hy vọng rằng, không ai trong tâm trí bên phải của họ sẽ thiết kế nó theo cách hiện nay và hy vọng ngay cả những người không có suy nghĩ đúng đắn của họ sẽ không chọn định danh theo cách họ được sử dụng trong thư viện stream. (C'mon, có các chức năng được đặt tên egptr, sputnuflowcũng như underflow. Điều đó thật vui nhộn!)
sbi

@sbi Tôi phát hiện ra rằng thư viện iostream không còn được coi là thư viện chuẩn cho C ++. Và như bạn đã đề cập, các định danh của nó không hữu ích như một quy ước lập trình ;-)
umlcat

2
@umlcat: Thư viện iostreams (trong templatized từ khi được chấp nhận cho C ++ 03) chắc chắn được coi là một phần của thư viện chuẩn C ++.
sbi

Tôi cũng đã đi theo con đường tương tự. Tôi nghĩ lý do tôi có là camelCase dễ gõ hơn một chút và tôi muốn lười biếng ở đó. Sau này tôi mới biết mình đã dành nhiều thời gian hơn để đọc và tái cấu trúc mã của mình hơn là viết nó, và sn_case dễ đọc hơn. Vì vậy, đó là tất cả về giảm thiểu chi tiêu năng lượng. Bây giờ tôi đang chơi với việc sử dụng tên viết thường cho các lớp. Tuy nhiên, điều đó là độc đáo, tuy nhiên tôi nghĩ rằng việc chuyển đổi nó xung quanh và vượt qua các Trường hợp quan trọng và các kiểu hạ cấp thực sự giúp cải thiện khả năng đọc mã của tôi. Tôi nghĩ có lẽ đây là con đường để đi. Uppercase những gì quan trọng, như trong tiếng người.
PSkocik

19

Trước tiên, hãy đồng ý rằng TẤT CẢ NHỮNG LỜI NÓI là một chướng mắt và nên được giảm thiểu.

Do đó, trong C và C ++, nó được sử dụng như một quy ước cho các macro và chỉ các macro, bởi vì các macro đều xấu như nhau, không nói xấu.

Đầu C không có const, vì vậy hằng số phải được biểu thị dưới dạng macro. Ngoài ra, trong những ngày đầu đó, các chương trình ngắn hơn rất nhiều, do đó, các thực tiễn không tốt ngày nay có thể được sử dụng (ví dụ: IIRC Brian Kernighan đã viết mã với rất nhiều macro không viết hoa). Và ngoài ra, vào thời đó, bàn phím không có chữ thường đã tồn tại; Tôi đã sử dụng một cái như vậy, trên máy tính Na Uy Tandberg EC-10, khoảng 1980 hoặc 1979 tôi nghĩ là vậy.

Vì vậy, Java đã chọn quy ước viết hoa cho các hằng từ đầu C. Trong khi đó, và có lẽ ngay cả trước đó (tôi không chắc về niên đại ở đây), C có các hằng số. Tuy nhiên, trong khi tất nhiên một số / nhiều lập trình viên C đã bị mắc kẹt trong quy ước trước đây của các hằng số là các macro chữ hoa, các lập trình viên C ++ lại hợp lý hơn.

Vấn đề lớn hiện nay là khi mọi người được dạy Java trước, hoặc C (với các quy ước từ thời trung cổ) trước, sau đó đến C ++, mang theo quy ước viết hoa xấu đó với họ.

Vì thế,

    int const answer = 42;    // Nice, good, OK.
    const int ANSWER = 0x2A;  // Ouch!
    #define COMPANYNAME_ANSWER 052  // Oh kill me, please.

Vâng, bạn có thể nghĩ rằng tôi đã đề cập đến bàn phím chỉ viết hoa trong trò đùa. Ôi không. Bởi vì đó đơn thuần là giới hạn công nghệ cổ xưa nhất, lâu đời nhất đã thúc đẩy các quy ước đặt tên, hoặc ít nhất ảnh hưởng đến mức độ sai / đúng của chúng. Tiếp theo, có vấn đề về truyền nối tiếp 7 bit, gây ra các vấn đề tương ứng với mã ký tự (mã hóa ký tự báo), điều đó có nghĩa là bạn phải hạn chế các chữ cái trong bảng chữ cái tiếng Anh, từ A đến Z.

Thật ra tôi khuyên bạn vẫn nên làm điều đó. Đó là nơi chúng ta đang ở! Chúng tôi không có thêm.

Hiện tại, kể từ năm 2011, C ++ tiêu chuẩn hỗ trợ Unicode chung trong các tên (và đã được thực hiện từ năm 1998), trong khi việc triển khai C ++ thực tế thì không. Cụ thể, trình biên dịch g ++ là nhân vật quốc gia bị thách thức. Nó bắt nguồn từ giới hạn công nghệ thời kỳ đen tối.

Vì thế,

    double blueberryJamViscosity  = 0.0;    // OK
    double blåbærsyltetøyViskositet = 0.0;  // Ouch!

Cuối cùng, về chủ đề của dấu gạch dưới so với chữ in hoa xen kẽ,

  • Dự trữ một hình thức dễ dàng nhận ra cho tên loại.
  • Dự trữ TẤT CẢ TĂNG TRƯỞNG cho các macro.
  • Hãy kiên định.

Tôi nghĩ rằng, thực sự, ngoại trừ các quy tắc như "thường tránh tên một chữ cái ngoại trừ (vòng lặp, mẫu param, blah blah)" và "tránh sử dụng l, dễ nhầm với 1" và "tránh viết hoa O, dễ nhầm lẫn với 0 ". Ngoài ra, tất nhiên, tránh sử dụng các tên dành riêng như bắt đầu bằng dấu gạch dưới, theo sau là chữ hoa, chứa hai dấu gạch dưới liên tiếp hoặc bắt đầu bằng dấu gạch dưới và nằm trong không gian tên toàn cục.

Chúc mừng & hth


Alf, ISTR Stroustrup đề cập đến việc sao chép D & E C consttừ C ++, vì vậy điều này đã xảy ra từ rất lâu rồi, và rất lâu trước Java, có lẽ là cho C89.
sbi

2
Ồ, và một sự chân thành +1cho "Hãy kiên định!" Đọc nó tôi tự hỏi tại sao tôi quên đề cập đến điều này, quy tắc quan trọng nhất trong câu trả lời của tôi, khi đó là câu tôi không bao giờ quên nói với các học sinh của mình. Tôi cho rằng bạn sẽ tha thứ cho tôi nếu bây giờ tôi thêm nó vào câu trả lời của tôi như một suy nghĩ lại?
sbi

2

Tôi thường có xu hướng gắn bó với quy ước mà tôi thấy nhiều nhất trong các cơ sở mã hiện có cho ngôn ngữ. Trong trường hợp của C ++, tôi thường thấy camelCase. Trong trường hợp của Ruby hoặc PHP, tôi thường thấy Stuff_like_this.

Tuy nhiên, thực tế mà nói, điều quan trọng nhất là bạn chọn một quy ước kiểu không hoàn toàn điên rồ (dOnT_dO_tHiS) và nhất quán với nó. Làm cho nó để phong cách không thay đổi trong suốt mã cho một dự án cụ thể. Nếu bạn đang làm việc trên một dự án hiện có, bạn sẽ muốn đi theo phong cách đã có.


1

Chà, có những hệ thống Hungary thực sự phổ biến ngay cả bây giờ, nhưng tôi thà cắt cổ họng của mình còn hơn là khuyên dùng nó. Ứng dụng Hungary tốt hơn vì các dấu chú thích của nó thực sự là biểu thị cho ngữ nghĩa, mặc dù tôi cảm thấy rằng nó quá nhạy bén với chữ viết tắt khi một từ ngắn sẽ làm. (Để sử dụng ví dụ từ trang Wikipedia đó, tại sao sử dụng rwcho hàng khirow chỉ dài một ký tự? Không giống như thiếu nguyên âm toàn cầu.)

Trên thực tế, điều quan trọng nhất là tuân theo các quy ước của những người bạn đang làm việc cùng . Có thật không. Hầu hết các quy ước hoạt động đủ tốt, đặc biệt là nếu được sử dụng nhất quán. Sự không nhất quán là tồi tệ nhất (thậm chí nhiều hơn so với Hệ thống Hungary, điều mà tôi ghét). Và nếu bạn chỉ có một mình, hãy sử dụng bất cứ thứ gì bạn muốn.


1

Từ những gì tôi đã thấy, nó khác nhau giữa các dự án.

Các dấu gạch dưới được nhúng có lẽ truyền thống hơn / được sử dụng phổ biến hơn trong C trên Unix. Thư viện chuẩn cũng tuân theo điều này, vì vậy nó nên gần như chắc chắn được coi là mặc định, được sử dụng, trừ khi có đủ mã hiện sử dụng ước khác để hoàn toàn buộc sử dụng mà ước khác.

Windows (ví dụ) sử dụng vỏ lạc đà cho hầu hết các chức năng của nó, vì vậy khá nhiều người phát triển cho Windows cũng làm như vậy. Điều này cũng khá phổ biến ở những người thực sự quen thuộc với các ngôn ngữ khác và cố gắng đối xử với C ++ như thể nó chỉ là một biến thể kỳ lạ của một thứ khác.


1

Tôi đã sử dụng cả thư viện tiêu chuẩn và boost làm tài liệu tham khảo cho các quy ước đặt tên. Tuy nhiên, có một vấn đề với giải pháp này.

Thư viện chuẩn sử dụng quy ước đặt tên được thiết kế để cố gắng giảm xung đột với mã của bạn. Một phần của giải pháp là sử dụng tất cả các chữ cái viết thường. Do đó, việc sử dụng dấu gạch dưới thay vì camelCase.

Tôi thấy rằng camelCase có thể đọc được. PascalCase thường được sử dụng cho các tên lớp vì nó đại diện cho tương đương với một danh từ thích hợp. Tuy nhiên, tôi sẽ phá vỡ quy tắc đó đối với functor, đại diện nhiều hơn cho động từ.

Tôi cố gắng không sử dụng macro. Tuy nhiên khi tôi làm, các macro được tạo ra trông giống như các hàm khi chúng có thể. Tôi cũng sử dụng các giá trị const hoặc enum thay cho các hằng số kê khai, hơn nữa tránh tất cả các chữ hoa. Tôi thường đặt tiền tố cho các ký hiệu này bằng 'k' để chỉ ra rằng chúng là hằng số.

// instead of a manifest constant
#define HOURS 24

// use const
const int kHours = 24; 

// or enum
enum {
    kHours   = 24,
    kMinutes = 60
};

0

Tài liệu tham khảo này mô tả một quy ước đặt tên khá giống với quy ước mà tôi từng thấy được sử dụng thành công ở ít nhất ba công ty tôi từng làm việc trong quá khứ.

Trái với câu trả lời trước đó, tôi sẽ tránh tuân theo quy ước đặt tên của Thư viện chuẩn C ++ trong mã của riêng tôi, nếu không vì lý do nào khác ngoài việc tránh xung đột tên với Thư viện chuẩn.

Câu trả lời SO trước đây về một chủ đề liên quan cũng có thể được quan tâm: /programming/228783/what-are-the-rules-about-USE-an-underscore-in-ac-identifier


Umm, bạn có thể sử dụng quy ước đặt tên giống nhau mà không sử dụng cùng tên ... và nếu bạn thực sự muốn cùng tên, bạn vẫn được bảo vệ bởi không gian tên, ví dụ std::stringvs gnawme::string.
einpoklum
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.