충돌

2012-10-10 6 views
5

가능한 중복 :
Members vs method arguments access in C++충돌

I가 x, y, widthheight 같은 일부 멤버를 가지고있는 클래스입니다. 생성자에서 나는이 작업을 수행 할 것입니다 :

A::A(int x, int y, int width, int height) 
{ 
    x = x; 
    y = y; 
    width = width; 
    height = height; 
} 

이 정말 이해가되지 않으며 ++ g 컴파일 할 때 xy, widthheight 이상한 값 (예를 들어, -1405737648)이된다.

이러한 명명 충돌을 해결하는 최적의 방법은 무엇입니까?

+3

Euh, 인수 이름에'a'를 추가합니까? –

+0

'A :: A (int xa, int ya, int widtha, int heighta)' – corazza

+0

만약 당신이 우아하고 싶다면, 영어로 불명확 한 기사를 만드는'a'를 미리 보냅니다 :'anX, aY, aWidth, aHaight' 같은 식별자를 사용할 수는 없습니다. 동일한 식별자를 사용하여 동일한 범위에서 두 개의 다른 변수를 참조 할 수는 없습니다. 내 대답을 보라. –

답변

17

동일한 이름을 가진 잘 초기화 목록을 사용할 수 있습니다

A::A(int x, int y, int width, int height) : 
    x(x), 
    y(y), 
    width(width), 
    height(height) 
{ 
} 

대안이 같은 이름을 갖고 싶어하지 않을 경우, 다른 이름을 사용하는 것입니다.

//data members 
int x_; 
int y_; 
int width_; 
int height_; 
//constructor 
A::A(int x, int y, int width, int height) : 
    x_(x), 
    y_(y), 
    width_(width), 
    height_(height) 
{ 
} 

을하지만 첫번째 제안에 아무 문제가 없습니다 : 일부 헝가리어 표기법의 변화가 마음에 온다 (나는이에 대한 몇 가지 증오를 얻을 수 있습니다).

+0

17.4.3.1.2/1 : 밑줄로 시작하는 각 이름은 전역 네임 스페이스에서 이름으로 사용하기위한 구현에 예약되어있다. –

+0

@JohnDibling 매크로에만 적용되는 이유는 무엇이라고 생각하십니까? 오 잘 ... 내가 작성한 오래된 코드를 다시 볼 때 내가 싫어할 것이 한가지 더 있습니다. D –

+0

헝가리 표기법에 무엇이 잘못 되었나요? ;) 실제로 이것은 접두어로 된 이름이지만 헝가리 표기법의 변형은 아닙니다. –

2

생성자의 초기화 목록을 사용하여 문제를 피할 수 있지만 데이터 멤버의 명명 규칙을 따르면 (예 : _ 또는 후행 m_) 좋습니다. 그렇지 않으면 이름 충돌이있을 가능성이 매우 높습니다. 특히 xy과 같은 이름의 회원이있는 경우 이름 충돌이 발생할 가능성이 큽니다.

class A 
{ 
    public: 

    A(int x, int y, int width, int height) : x_(x), y_(y), with_(width), height_(height) {} 

    int x_; 
    int y_; 
    int width_; 
    int height_; 
}; 
+0

나는 종종이 (후행 밑줄) 대회를 보았습니다 - 그 기원을 알고 있습니까? 어떤 힌트 주셔서 감사합니다. – Wolf

+0

this->는 지역 범위에서 모호성을 제거하는 좋은 방법이기도합니다. – partyd

5

다음과 같이이 문제가 this 포인터를 사용하는 것입니다 해결하기 위해 특정 패턴을 (선호 초기화 목록을 사용하여 반대) 당신이 생성자에서 할당을 사용해야하는 경우 :

this->a = a; 
0

생성자 인수의 이름을 변경할 수 있습니다. 당신은 당신이을 초기화되지 않은 실제 인스턴스 변수를 떠나, 자신에 생성자의 인수를 지정하고

A::A(int x, int y, int width, int height) 
{ 
    x = x; 
    y = y; 
    width = width; 
    height = height; 
} 

를 쓸 때 당신이 가짜 값을 받고있어, 그 이유입니다.

내가 제안 (널리 사용) 일반적인 솔루션은 생성자 메서드의 인수의 이름을 변경하는 것입니다 :

A::A(int x_initial, int y_initial, int width_initial, int height_initial) 
{ 
    x = x_initial; 
    y = y_initial; 
    width = width_initial; 
    height = height_initial; 
} 
+0

그래, 그게 내가 한 일이지만, "_initial"대신에 "a"를 덧붙였다. – corazza

+0

@Bane 그리고 그게 뭐가 잘못 됐니? –

+0

글쎄 그것은 "못생긴"해결책 인 것 같아요. 나는 그것이 생성자에 대한 나의 이해에 뭔가 잘못된 것이 있다고 생각 했었습니다. ... – corazza

2

모든 가능한 경우를, 그것은 초기화 목록을 통해 데이터 멤버를 설정하는 것이 좋습니다, 이 경우 그림자 구성원 이름에 대한 인수에는 문제가 없습니다. 또 다른 방법은 생성자의 본문에 this->foo = foo;을 사용하는 것입니다. setter에도 비슷한 문제가 있지만 이제 초기화 프로그램 목록 솔루션을 사용할 수 없습니다. 너는 this->foo = foo;을 붙잡 았어. 아니면 그냥 인자와 멤버에 다른 이름을 써라.

어떤 사람들은 실제로 데이터 멤버를 그늘지게하는 인수를 싫어합니다. 다중 코딩 표준은 이것을 절대하지 않을 것이라고 명시 적으로 말하고 있습니다. 다른 사람들은 적어도 생성자와 설정자를 위해 이런 종류의 그림자가 고양이의 야옹이라고 생각합니다. 나는 이런 종류의 음영을 "should"(그러나 "~해야한다") 실천으로 지정 한 하나 또는 두 개의 코딩 표준 (그러나 나는 기억하지 못한다)을 읽었던 것을 기억합니다.

최종 옵션 하나는 함수 선언에서 쉐도 잉을 사용하여 함수가하는 일에 대한 힌트를 제공하지만 구현시 고유 한 이름을 사용하는 것입니다.

업데이트 : "섀도 잉"이란 무엇입니까?

#include <iostream> 

void printi (int i) { std::cout << "i=" << i << "\n"; } 

int i = 21; 

int main() { 
    printi (i); 
    int i = 42; 
    printi (i); 
    for (int i = 0; i < 3; ++i) { 
     printi (i); 
     int i = 10; 
     printi (i); 
    } 
    printi (i); 
} 

i, int i=10의 가장 안쪽 선언은, 차례 차례로 전역 변수 i 그림자 기능 범위에서 선언 된 변수 i을 어두운 영역 for 문에서 선언 된 변수 i 그림자. 클래스 A 그림자에 대한 기본이 아닌 생성자에 손을 문제에

, 인수 x, y, widthheight 그 인수와 같은 이름을 가진 구성원 데이터.

귀하의 width=width;는 아무것도하지 않았다 때문에 인수 width 그림자 (가죽) 데이터 멤버 width. 서로 다른 범위에서 선언 된 동일한 이름을 가진 두 개 이상의 변수가있는 경우 승자는 항상 가장 안쪽 범위의 이름입니다. 일반적으로 항상 가장 안쪽에있는 스코어가있는 이름입니다.

+0

당신은 정확히 "섀도 잉"이라고 부릅니까? – corazza

+0

@Bane - "섀도 잉"이란 무엇입니까? 음영 : (1) CS 101 학생들이 범위를 이해하는지 여부를 테스트하는 데 사용되는 고문 장치. (2) 어떤 범위에서 선언 된 변수가 어떤 외부 범위에서 선언 된 변수와 같은 이름을 가질 때. (3) 당신의 생성자로 무엇을했는지. (4)'-Wshadow'로 컴파일함으로써 잠재적 인 문제. (5) 업데이트 된 답변보기. –

+0

감사합니다. – corazza