Có phải đó là một ý tưởng hay cho các nhà hàng #define me (* này) không?


19

Macro này có thể được định nghĩa trong một số tiêu đề toàn cầu, hoặc tốt hơn, như là một tham số dòng lệnh của trình biên dịch:

#define me (*this)

Và một số ví dụ sử dụng:

some_header.h:

inline void Update()
{
    /* ... */
}

chính.cpp:

#include "some_header.h"

class A {
public:
    void SetX(int x)
    {
        me.x = x;   
        me.Update(); 
    }

    void SomeOtherFunction()
    {
        ::Update();
    }

    /*
        100 or more lines
        ... 
    */

    void Update()
    {
        // ... 
    }

    int x;  
};

Vì vậy, trong một phương thức lớp khi tôi truy cập một thành viên lớp, tôi luôn sử dụng mevà khi truy cập một định danh toàn cầu tôi luôn sử dụng ::. Điều này cung cấp cho người đọc không quen thuộc với mã (có thể là bản thân tôi sau một vài tháng) thông tin địa phương về những gì được truy cập mà không cần phải tìm ở nơi nào khác. Tôi muốn xác định mebởi vì tôi thấy việc sử dụng this->ở mọi nơi quá ồn ào và xấu xí. Nhưng có thể #define me (*this)được coi là một thực hành C ++ tốt? Có một số điểm có vấn đề thực tế với mevĩ mô? Và nếu bạn là lập trình viên C ++ sẽ là người đọc một số mã sử dụng memacro, bạn có muốn hay không?

Chỉnh sửa: Bởi vì nhiều người tranh luận không sử dụng contraicaly contra me, nhưng contra contra rõ ràng điều này. Tôi nghĩ có thể không rõ lợi ích của "rõ ràng ở mọi nơi" là gì.

Lợi ích của "rõ ràng này ở khắp mọi nơi" là gì?

  • Là một người đọc mã, bạn chắc chắn những gì được truy cập và bạn có thể tập trung vào những thứ khác nhau hơn là xác minh - trong một số mã ở xa - đó thực sự được truy cập những gì bạn nghĩ là được truy cập.
  • Bạn có thể sử dụng chức năng tìm kiếm cụ thể hơn. Tìm kiếm " this->x" có thể cung cấp cho bạn nhiều kết quả mong muốn hơn là chỉ tìm kiếm " x"
  • Khi bạn đang xóa hoặc đổi tên một số thành viên, trình biên dịch đáng tin cậy sẽ thông báo cho bạn tại những nơi mà thành viên này được sử dụng. (Một số chức năng toàn cầu có thể có cùng tên và tồn tại cơ hội bạn có thể đưa ra lỗi nếu bạn không sử dụng rõ ràng điều này).
  • Khi bạn tái cấu trúc mã và tạo hàm không phải thành viên từ thành viên (để đóng gói tốt hơn), điều này cho thấy bạn phải chỉnh sửa và bạn có thể dễ dàng thay thế nó bằng con trỏ đến thể hiện của lớp được đưa ra dưới dạng tham số hàm không phải thành viên
  • Nói chung khi bạn đang thay đổi mã, sẽ có nhiều lỗi hơn khi bạn không sử dụng điều này rõ ràng hơn là khi bạn đang sử dụng điều này rõ ràng ở mọi nơi.
  • Rõ ràng điều này ít ồn ào hơn explicit m_ Rõ khi bạn đang tham gia thành viên từ bên ngoài ( object.membervs object.m_member) (nhờ @Kaz để phát hiện điểm này)
  • Giải thích điều này giải quyết phổ quát vấn đề cho tất cả các thành viên - thuộc tính và phương thức, trong khi „m_ xông hoặc tiền tố khác chỉ có thể sử dụng được cho các thuộc tính.

Tôi muốn đánh bóng và mở rộng danh sách này, cho tôi biết nếu bạn biết về những lợi thế khác và sử dụng các trường hợp để giải thích điều này ở mọi nơi .


3
Bạn nên tránh có các đối số chức năng và các thành viên có cùng tên, cũng như tránh "điều này" rõ ràng.
pjc50

4
Nhắc tôi về mã VB của sếp tôi. Me Me Me ở khắp mọi nơi. Nghe có vẻ ích kỷ. : p Dù sao, câu trả lời cho đến nay nói lên tất cả.
MetalMikester

19
Đó là một ý tưởng tuyệt vời! Và đối với những người đến từ một nền tảng Python, tại sao không #define self (*this)? Bạn thậm chí có thể trộn cả hai macro và có một số tệp bắt chước VB và các Python khác. :)
đăng nhập

11
Tại sao không chỉ cần đi tất cả ra ngoài, và làm: #include "vb.h", #Include pascal.h, hay #include FOTRAN.hvà có người bên cạnh chạm vào mã của bạn trình TDWTF .
Dan Neely

4
Oh làm ơn, chỉ là không. Bạn có thể tự cứu mình một số rắc rối bằng cách chỉ khai báo các thuộc tính là me_x.
Gort Robot

Câu trả lời:


90

Không có nó không phải là.

Hãy nhớ rằng lập trình viên sẽ duy trì mã của bạn trong vài năm kể từ bây giờ sau khi bạn rời khỏi đồng cỏ xanh hơn và tuân theo các quy ước chung về ngôn ngữ bạn sử dụng. Trong C ++, bạn hầu như không bao giờ phải viết this, bởi vì lớp được bao gồm theo thứ tự độ phân giải ký hiệu và khi một biểu tượng được tìm thấy trong phạm vi lớp, this->được ngụ ý. Vì vậy, đừng viết nó như mọi người.

Nếu bạn thường bị nhầm lẫn biểu tượng nào đến từ phạm vi lớp, cách tiếp cận thông thường là sử dụng mẫu đặt tên chung cho các thành viên (các trường và đôi khi là các phương thức riêng tư; tôi đã không thấy nó được sử dụng cho các phương thức công khai). Những cái phổ biến bao gồm hậu tố có _hoặc tiền tố với m_hoặc m.


12
"Trong C ++, bạn gần như không bao giờ phải viết điều này" đó là một quy ước hoàn toàn không liên quan đến câu hỏi. Một số người (như tôi) thích viết thismột cách rõ ràng để làm rõ rằng biến không phải là cục bộ của phương thức. Câu hỏi ở đây là về việc liệu macro mecó nên tồn tại hay không, liệu thiscó nên sử dụng cái gì không.
Mehrdad

8
@Mehrdad: Bởi vì OP nói rõ rằng anh ta đang sử dụng me.thay vì this->. Vì không có nhu cầu nên this->không có nhu cầu me.và do đó không cần macro.
Martin York

11
@LokiAstari: Không có gì trong câu hỏi ngay cả gợi ý từ xa tại OP tự hỏi liệu this->"có cần thiết" không. Trên thực tế, OP nói rằng anh ta đang sử dụng this->mặc dù thực tế là không cần thiết. Câu hỏi là về việc có me.nên sử dụng thay vì this-> , câu trả lời này không thực sự trả lời.
Mehrdad

4
@Mehrdad: Nhưng chỉ đặt có hoặc không làm cho một câu trả lời rất nhàm chán. Do đó, những lời giải thích thường khá hữu ích trong việc giải thích cách đạt được câu trả lời (được giải thích bằng cách trả lời ). Kết luận là không được sử dụng vì OP có thái độ sai lầm khi bắt đầu sử dụng thisvà do đó cần phải thảo luận về điểm đó để đạt được kết luận hoàn toàn cân bằng.
Martin York

1
+1 để giải thích lý do tại sao, thay vì chỉ nói "Không, đó là một thực tiễn tồi".
dùng253751

42

Vì vậy, bạn muốn tạo một ngôn ngữ mới. Sau đó, làm như vậy, và không làm tê liệt C ++.

Có một số lý do để không làm điều đó:

  1. Mọi tiêu chuẩn mã hóa thông thường sẽ đề xuất để tránh các macro ( đây là lý do )
  2. Việc duy trì mã với các macro như vậy là khó hơn. Mọi người lập trình trong C ++ đều biết nó thislà gì và bằng cách thêm macro như vậy, bạn thực sự đang thêm một từ khóa mới. Nếu mọi người giới thiệu thứ gì đó họ thích thì sao? Mã sẽ trông như thế nào?
  3. Bạn không nên sử dụng (*this).hoặc hoàn this->toàn, ngoại trừ trong một số trường hợp đặc biệt (xem câu trả lời này và tìm kiếm "this->")

Mã của bạn không khác với #define R return, mà tôi đã thấy trong mã thực tế. Lý do? Ít gõ!


Đi hơi lạc đề, nhưng ở đây tôi sẽ mở rộng ở điểm 3 (không sử dụng (*this).hoặc this->trong một lớp học).

Trước hết, (*this).hoặc this->được sử dụng để truy cập các biến thành viên hoặc chức năng của đối tượng. Sử dụng nó là vô nghĩa và có nghĩa là gõ nhiều hơn. Ngoài ra, đọc mã như vậy là khó khăn hơn, bởi vì có nhiều văn bản hơn. Điều đó có nghĩa là bảo trì khó khăn hơn.

Vì vậy, những trường hợp mà bạn phải sử dụng là this->gì?

(a) Không may chọn tên của đối số.

Trong ví dụ này, this->là bắt buộc, vì đối số có cùng tên với biến thành viên:

struct A {
  int v;
  void foo( int v ) {
    this->v =v;
  }
};

(b) Khi xử lý các mẫu và kế thừa (xem phần này )

Ví dụ này sẽ không biên dịch được, vì trình biên dịch không biết biến nào được đặt tên vđể truy cập.

template< typename T >
struct A {
  A(const T& vValue):v(vValue){}

  T v;
};

template< typename T >
struct B : A<T>
{
    B(const T& vValue):A<T>(vValue){}

    void foo( const T & newV ) {
      v = newV;
    }
};

1
"Vì vậy, bạn muốn tạo một ngôn ngữ mới. Sau đó, làm như vậy và không làm tê liệt c ++." - Tôi không đồng ý. Một điểm mạnh của C và C ++ là tính linh hoạt của chúng. OP không làm tê liệt C ++, chỉ sử dụng tính linh hoạt của nó theo một cách cụ thể để giúp người đó dễ dàng viết mã hơn.
dùng253751

2
@immibis Phải. Những gì dễ dàng hơn cho anh ta, là khó khăn hơn cho mọi người khác. Khi bạn làm việc trong một nhóm, việc đưa những điều vô nghĩa đó vào mã sẽ không khiến bạn rất thuận lợi.
BЈовић

2
Câu trả lời của bạn không khác với "định nghĩa là xấu xa".
Ông Lister

7
@MrLister Câu trả lời của tôi là "ngu ngốc định nghĩa là xấu xa". Macro trong câu hỏi là ngu ngốc để sử dụng, và như tôi đã chỉ ra, không cần thiết chút nào. Mã này là tốt và thậm chí tốt hơn mà không cần *this.this->
Bовић

1
@Mehrdad Có phải mọi người vẫn thêm tiền tố và hậu tố vào các biến thành viên? Tôi nghĩ rằng nó đã được "sửa" với những cuốn sách như Clean Code . this->cũng hữu ích như autotrong pre-c ++ 11. Nói cách khác, nó chỉ làm tăng tiếng ồn mã.
BЈовић

26

Tôi đề nghị không làm điều này. Điều này mang đến cho người đọc không quen thuộc với macro của bạn một " WTF " lớn bất cứ khi nào anh ta thấy điều này. Mã không thể đọc được nhiều hơn khi phát minh ra "các quy ước mới" so với các quy ước được chấp nhận chung mà không có nhu cầu thực sự.

sử dụng cái này-> ở mọi nơi quá ồn ào và xấu xí

Điều đó có vẻ như vậy đối với bạn, có thể vì bạn đã lập trình rất nhiều ngôn ngữ bằng từ khóa me(Visual Basic, tôi đoán vậy?). Nhưng trên thực tế, đó chỉ là vấn đề làm quen với nó - this->khá ngắn và tôi nghĩ rằng hầu hết các lập trình viên C ++ có kinh nghiệm sẽ không đồng ý với ý kiến ​​của bạn. Và trong trường hợp trên, việc sử dụng this->hoặc sử dụng không mephù hợp - bạn sẽ có được sự lộn xộn nhỏ nhất bằng cách loại bỏ các từ khóa đó khi truy cập các thành viên dữ liệu bên trong các hàm thành viên.

Nếu bạn muốn các biến thành viên riêng của bạn được phân biệt với các biến cục bộ, hãy thêm một liên kết nào đó m_làm tiền tố hoặc dấu gạch dưới làm hậu tố cho chúng (nhưng như bạn có thể thấy ở đây , ngay cả quy ước này cũng "quá ồn" đối với nhiều người).


12
_nên được hậu tố ; làm tiền tố, nó được dành riêng cho các biểu tượng bên trong của các thư viện chuẩn và phần mở rộng của nhà cung cấp.
Jan Hudec

4
@JanHudec Chỉ khi nó bắt đầu bằng __(hai dấu gạch dưới) hoặc dấu gạch dưới theo sau là chữ in hoa. Một dấu gạch dưới duy nhất theo sau là một chữ cái viết thường là tốt, miễn là nó không nằm trong không gian tên toàn cầu.
Eric Finn

1
@EricFinn: Tôi đã kết hợp hai quy tắc thành một. Hai dấu gạch dưới hoặc dấu gạch dưới theo sau là chữ in hoa là dành cho các ký hiệu bên trong và dấu gạch dưới đơn theo sau là chữ in thường dành cho các phần mở rộng dành riêng cho hệ thống. Các ứng dụng cũng không nên sử dụng.
Jan Hudec

@JanHudec Không biết quy tắc cho các tiện ích mở rộng dành riêng cho hệ thống. Tuy nhiên, tôi sẽ để lại bình luận trước để cung cấp một số bối cảnh cho nhận xét của bạn.
Eric Finn

2
@JanHudec: Chữ thường dành cho các tiện ích mở rộng dành riêng cho hệ thống? Bạn có thể gửi một tài liệu tham khảo đến một phần của tiêu chuẩn C ++ chỉ ra điều này không?
Mehrdad

18

Xin đừng làm thế! Tôi đang cố gắng đối phó với một cơ sở mã lớn, nơi các macro có mặt khắp nơi để lưu gõ. Điều tệ hại khi định nghĩa lại điều này với tôi là bộ tiền xử lý sẽ thay thế nó ở mọi nơi ngay cả khi điều này không nằm trong phạm vi / không áp dụng, ví dụ như một chức năng độc lập, đồng nghiệp của bạn có thể có một biến cục bộ gọi tôi ở một nơi khác .. Anh ấy sẽ không vui khi gỡ lỗi ... Cuối cùng, bạn có các macro mà bạn không thể sử dụng trong tất cả các phạm vi.


6

KHÔNG!

Chỉ cần tưởng tượng sự nhầm lẫn sẽ xảy ra nếu ai đó # bao gồm tiêu đề đó, không biết thủ thuật của bạn và ở nơi khác trong tệp của họ, họ có một biến hoặc hàm gọi là "tôi". Họ sẽ bị bối rối khủng khiếp bởi bất cứ thông báo lỗi khó hiểu nào sẽ được in.


Trong thực tế, họ hoàn toàn có khả năng di chuột qua "tôi" với IDE của họ và xem định nghĩa.
dùng253751

2
@immibis: Tuy nhiên, trên thực tế, họ cũng có khả năng nói điều gì đó như "ai đã viết chuyện tào lao này?". : P
cHao

@immibis: hầu hết các lập trình viên hàng đầu tôi làm việc không sử dụng chuột - quá chậm.
JBRWilkinson

Thật vậy: đẩy điều này trong một tiêu đề là vấn đề thực tế. Nếu bạn sử dụng nó trong tập tin cpp của bạn, tôi không thấy vấn đề gì cả. Nếu chúng tôi có pragma đẩy theo tiêu chuẩn, tôi sẽ tư vấn làm thế nào để làm điều này trong một tiêu đề, nhưng chúng tôi không. Nhắc lại theo tôi. #defines là toàn cầu.
Joshua
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.