"#define me (* this)"는 것이 좋은 생각입니까?


19

이 매크로는 일부 글로벌 헤더에서 또는 컴파일러 명령 행 매개 변수로 정의 할 수 있습니다.

#define me (*this)

그리고 일부 사용 예 :

some_header.h :

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

main.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;  
};

따라서 클래스 멤버에 액세스 할 때 클래스 메서드에서 항상을 사용 me하고 전역 식별자에 액세스 할 때 항상을 사용 ::합니다. 이것은 코드에 익숙하지 않은 독자에게 (어쩌면 몇 달 후에 나 자신에게) 다른 곳을 볼 필요없이 액세스 된 것에 대한 현지화 된 정보를 제공합니다. 모든 곳에서 너무 시끄럽고 못생긴 me것을 사용하기 때문에 정의하고 싶습니다 this->. 그러나 #define me (*this)좋은 C ++ 연습으로 간주 될 수 있습니까? me매크로에 실용적인 문제가 있습니까? 그리고 C ++ 프로그래머로서 me매크로를 사용하는 일부 코드의 독자가 된다면 그것을 원하십니까?

편집 : 많은 사람들이을 사용하여 구체적으로 대조를 주장하지는 me않지만 일반적으로 이것을 명시 적으로 대조합니다. "이 곳 어디에서나 명시 적"의 이점이 무엇인지 명확하지 않을 수 있습니다.

"이 곳 어디에서나 명시 적"의 이점은 무엇입니까?

  • 코드의 독자로서 당신은 무엇을 액세스했는지 확실하게 알고 있으며, 먼 코드에서 확인과는 다른 것에 집중할 수 있습니다.
  • 보다 구체적으로 검색 기능을 사용할 수 있습니다. "검색 this->x"만 검색보다 더 많은 원하는 결과를 얻을 수 있습니다 " x"
  • 일부 멤버를 삭제하거나 이름을 바꾸는 경우 컴파일러는이 멤버가 사용되는 위치를 확실하게 알려줍니다. (일부 전역 함수는 동일한 이름을 가질 수 있으며 명시 적으로 사용하지 않으면 오류가 발생할 수 있습니다.)
  • 코드를 리팩토링하고 멤버에서 멤버가 아닌 함수를 명시 적으로 만들 때 (더 나은 캡슐화를 위해) 이것은 편집해야하는 위치를 나타내며이를 멤버가 아닌 함수 매개 변수로 제공된 클래스의 인스턴스에 대한 포인터로 쉽게 바꿀 수 있습니다.
  • 일반적으로 코드를 변경하는 경우 명시 적으로 이것을 사용하지 않을 때 어디서나 명시 적으로 사용하는 경우보다 오류가 발생할 가능성이 더 큽니다.
  • 명시 적으로 이것은 외부에서 object.membervs. 멤버를 액세스 할 때 명시 적 "m_"보다 덜 시끄 럽습니다 ( object.m_member이 지점을 발견하기 위해 @Kaz 덕분에)
  • 명시 적으로 이것은 모든 멤버 (속성 및 메소드)에 대한 보편적 문제를 해결하는 반면, "m_"또는 다른 접두어는 속성에만 실용적으로 사용할 수 있습니다.

이 목록을 다듬고 확장하고 다른 장점과 사용 사례를 알고 있다면 어디에서나 명시 적으로 알려주십시오 .


3
명시적인 "this"를 피할뿐만 아니라 같은 이름의 함수 인수와 멤버를 사용하지 않아야합니다.
pjc50

4
상사의 VB 코드를 상기시킵니다. 나 나 어디 나. 이기적으로 들린다. : p 어쨌든, 대답은 지금까지 모든 것을 말합니다.
MetalMikester

19
훌륭한 아이디어입니다! 그리고 파이썬 배경에서 온 사람들에게 왜 안 #define self (*this)됩니까? 당신은 할 수 있습니다 모두 매크로를 혼합 하고 VB 등 파이썬을 모방 일부 파일이 있습니다. :)
logc

11
왜 그냥 모두 밖으로 이동하고,하지 : #include "vb.h", #Include pascal.h또는 #include FOTRAN.h당신의 코드에 제출 만지지 다음 사람이 TDWTF을 .
Dan Neely

4
아, 제발 안돼 속성을로 선언하면 문제를 해결할 수 me_x있습니다.
로봇

답변:


90

전혀 그렇지 않다.

녹색 목초지로 떠난 후 몇 년이 지난 지금부터 코드를 유지할 프로그래머를 염두에두고 사용하는 언어의 일반적인 규칙을 따르십시오. C ++에서는 this클래스가 심볼 확인 순서에 포함되어 있고 심볼이 클래스 범위에서 발견 될 때 this->암시 되기 때문에 거의 쓸 필요가 없습니다 . 모든 사람처럼 작성하지 마십시오.

클래스 범위에서 어떤 기호가 나오는지 종종 혼란스러워하는 경우 일반적인 접근 방식은 멤버 (필드 및 때로는 개인 메서드)에 공통 명명 패턴을 사용하는 것입니다. 공용 메서드에 사용되는 것을 보지 못했습니다). 일반적인 것들과 부기 포함 _하거나 함께 접두사 m_m.


12
"C ++에서는 거의 이것을 작성할 필요가 없습니다" 는 질문과 전혀 관련이없는 규칙입니다. 나와 같은 일부 사람들 this은 변수가 메서드의 로컬 변수가 아님을 명시 적으로 밝히기 위해 작성하는 것을 선호합니다 . 여기서 질문은 me사용해야하는 것이 아니라 매크로 가 존재해야하는지 this에 관한 것입니다.
Mehrdad

8
@Mehrdad : OP는 명시 적으로 me.대신 사용하고 있다고 말합니다 this->. 필요가 없기 때문에에 대한 this->필요가 없습니다 me., 따라서 매크로가 필요.
Martin York

11
@LokiAstari : 문제의 어떤 것도 OP this->가 " 필요한지 " 궁금해하는 것을 암시하지 않습니다 . 실제로 OP는 this->필요하지 않다는 사실에도 불구하고 사용 하고 있다고 말합니다 . 질문은 대신에me. 사용해야하는지 에 관한 것인데,이 답변은 실제로 대답하지 않습니다. this->
Mehrdad

4
@Mehrdad : 그러나 예 또는 아니오 만 넣으면 매우 지루한 답변이됩니다. 따라서 설명은 일반적으로 답변에 도달하는 방법을 설명하는 데 매우 유용합니다 (응답 방법에 의해 향상됨 ). OP는 사용에 관한 잘못된 태도를 가지고 있기 때문에 결론을 사용하지 않으므로 this그 점에 대한 논의는 완전히 균형 잡힌 결론을 달성해야합니다.
Martin York

1
왜 "아니오, 나쁜 습관입니다"라고 말하는 대신에 +1을 설명합니다.
user253751

42

따라서 새로운 언어를 만들고 싶습니다. 그런 다음 C ++을 손상시키지 마십시오.

하지 말아야 할 몇 가지 이유가 있습니다.

  1. 모든 일반적인 코딩 표준은 매크로를 피할 것을 제안합니다 ( 여기서 이유입니다 )
  2. 이러한 매크로로 코드를 유지 관리하기가 더 어렵습니다. C ++로 프로그래밍하는 모든 사람은 무엇인지 알고 있으며 this이러한 매크로를 추가하면 실제로 새 키워드를 추가하게됩니다. 모두가 좋아하는 것을 소개하면 어떻게 되나요? 코드는 어떻게 생겼습니까?
  3. 당신은 사용하지 말아야 (*this).또는 this->전혀, 특별한 경우를 제외합니다 ( 이 답변을 검색하십시오 "this->")

귀하의 코드는 #define R return실제 코드에서 보았던와 다르지 않습니다 . 이유? 타이핑이 적습니다!


주제와 약간가는, 그러나 여기에서 나는 점 3 (사용하지 않는을 확장하기 위하여려고하고 (*this).또는 this->클래스에서).

우선, (*this).또는 this->액세스 멤버 변수 또는 개체의 기능에 이용된다. 그것을 사용하는 것은 의미가 없으며 더 많은 타이핑을 의미합니다. 또한 더 많은 텍스트가 있기 때문에 이러한 코드를 읽는 것이 더 어렵습니다. 이는 유지 보수가 더 어렵다는 것을 의미합니다.

그렇다면 어떤 경우를 사용해야 this->합니까?

(a) 불행히도 인수 이름을 고릅니다.

이 예제에서는 this->인수가 멤버 변수와 이름이 같으므로 필수입니다.

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

(b)는 템플릿 및 상속 처리 할 때 (참조 )

컴파일러가 v액세스 할 명명 된 변수를 모르기 때문에이 예제는 컴파일에 실패 합니다.

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
"따라서 새로운 언어를 만들고 싶다. 그렇게하고 C ++를 무너 뜨리지 말아야한다." -동의하지 않습니다. C 및 C ++의 주요 장점은 유연성입니다. OP는 C ++을 방해하지 않고 특정 방식으로 유연성을 활용하여 코딩하기가 더 쉬워졌습니다.
user253751

2
@immibis 맞습니다. 그를 위해 더 쉬운 것은 다른 사람을 위해 더 어렵다. 팀에서 일할 때 그러한 말도 안되는 코드를 코드에 넣는 것이 그리 유리하지는 않습니다.
BЈовић

2
당신의 대답은 "정의는 악하다"와 다르지 않습니다.
Mr Lister

7
@MrLister 내 대답은 "멍청한 정의는 악하다"입니다. 질문의 매크로는 사용하기 어리 석고 내가 보여 주듯이 전혀 필요하지 않습니다. 코드는 좋은 더 나은없이 *this.하고this->
BЈовић

1
@Mehrdad 사람들이 여전히 멤버 변수에 접두사와 접미사를 추가하고 있습니까? Clean Code 와 같은 책으로 "고정"되었다고 생각했습니다 . c ++ 11 이전 this->과 같이 유용합니다 auto. 즉, 코드 노이즈 만 증가시킵니다.
BЈовић

26

나는 이것을하지 않는 것이 좋습니다. 이렇게하면 매크로에 익숙하지 않은 독자 가 이걸 볼 때마다 큰 " WTF "가됩니다. 실제로 필요한 규칙없이 일반적으로 받아 들여지는 규칙에 대해 "새로운 규칙"을 만들 때 코드를 더 쉽게 읽을 수 없습니다.

이-> 모든 곳에서 너무 시끄럽고 못 생겼습니다.

키워드를 사용하여 언어로 많은 프로그래밍을 수행했기 때문에 아마도 그렇게 보일 수 있습니다 me(Visual Basic, 추측합니까?). 그러나 실제로 그것은 그것에 익숙해지는 문제입니다- this->꽤 짧습니다. 경험이 많은 C ++ 프로그래머의 대부분은 귀하의 의견에 동의하지 않을 것이라고 생각합니다. 그리고 위의 경우 사용 this->또는 사용 me이 적절하지 않습니다. 멤버 함수 내부의 데이터 멤버에 액세스 할 때 해당 키워드를 남겨두면 최소한의 혼란을 얻을 수 있습니다.

개인 멤버 변수를 로컬 변수와 구별하려면 m_접두사로 링크 를 추가 하거나 접미사로 밑줄을 추가 하십시오 (그러나 여기 에서 볼 수 있듯이이 규칙은 많은 사람들에게 너무 시끄 럽습니다).


12
_해야 접미사 ; 접두사로서 표준 라이브러리 및 공급 업체 확장의 내부 기호 용으로 예약되어 있습니다.
Jan Hudec

4
@JanHudec 대문자로 시작하는 __밑줄 (밑줄 두 개) 또는 밑줄로 시작하는 경우에만 해당됩니다 . 단일 네임 스페이스 뒤에 소문자가 오는 것은 글로벌 네임 스페이스에없는 한 괜찮습니다.
Eric Finn

1
@EricFinn : 두 규칙을 하나로 결합했습니다. 두 개의 밑줄 또는 밑줄과 대문자는 내부 기호 용이고 밑줄과 소문자는 시스템 별 확장 용입니다. 응용 프로그램도 사용해서는 안됩니다.
Jan Hudec

@JanHudec 시스템 별 확장에 대한 규칙을 알지 못했습니다. 그래도 귀하의 의견에 대한 맥락을 제공하기 위해 이전 의견을 남겨 두겠습니다.
에릭 핀

2
@ JanHudec : 소문자는 시스템 별 확장을위한 것입니까? 이것을 나타내는 C ++ 표준 부분에 대한 참조를 게시 할 수 있습니까?
Mehrdad

18

제발 하지마! 매크로를 사용하여 입력을 저장하는 큰 코드베이스에 대처하려고합니다. 이것을 나에게 다시 정의 할 때의 나쁜 점은 프리 프로세서가 범위에 있지 않거나 적용되지 않는 곳, 예를 들어 독립형 함수 인 경우에도 어디서나 그것을 대체 할 수 있다는 것입니다. 동료의 동료는 다른 곳에 나라는 로컬 변수가있을 수 있습니다. 그는 디버깅에 만족하지 않을 것입니다 ... 모든 범위에서 사용할 수없는 매크로가 생깁니다.


6

아니!

누군가 #include가 해당 헤더를 가지고 있고, 당신의 트릭을 알지 못하고, 파일의 다른 곳에 "me"라는 변수 나 함수가있는 경우 발생할 혼란을 상상해보십시오. 어떤 오류 메시지가 인쇄 될 것인지에 대해 혼란 스러울 것입니다.


실제로, 그들은 IDE로 "나"위에 마우스를 올려 놓고 정의를 볼 가능성이 높습니다.
user253751

2
@immibis :하지만 실제로는 "누가이 쓰레기를 썼는가?"와 같은 말을 할 가능성이 있습니다. : P
cHao

@immibis : 내가 사용하는 대부분의 최고 코더는 마우스를 사용하지 않습니다-너무 느립니다.
JBR 윌킨슨

실제로 : 이것을 헤더에 넣는 것이 실제 문제입니다. cpp 파일에서 사용하면 전혀 문제가 없습니다. 우리가 pragma push를 표준으로 사용했다면 헤더 에서이 작업을 수행하는 방법을 조언하고 있지만 그렇게하지는 않습니다. 저를 반복하십시오. #defines는 세계적입니다.
Joshua
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.