2008-11-06 5 views
8

내가 이렇게 할 경우 :C++ const를 질문

// In header 
class Foo { 
void foo(bar*); 
}; 

// In cpp 
void Foo::foo(bar* const pBar) { 
//Stuff 
} 

컴파일러는 푸 :: foo에 대한 서명이 일치하지 않는 것을 불평하지 않습니다. 그러나 내가 가진 경우 :

void foo(const bar*); //In header 
void Foo::foo(bar*) {} //In cpp 

코드가 컴파일되지 않습니다.

무슨 일입니까? gcc 4.1.x를 사용하고 있습니다.

+0

두 번째 예제에서 *의 반대쪽에 const를 넣으려고 했습니까? 어떤 사람들은 그 의미의 차이점을 설명함으로써 대답하고 있으며 다른 사람들은 const가 cpp 또는 h 파일에 있는지 여부를 설명함으로써 대답하고 있습니다. –

+0

당신이 찾고있는 대답이 아닌 경우 질문이나 업데이트에 대한 질문을 선택해야합니다. –

답변

1

첫 번째 예에서 const 키워드는 의미가 없습니다. 당신은 포인터를 바꾸지 않을 것이라고 말하고 있습니다. 그러나 포인터가 값에 의해 전달되었으므로 포인터를 변경했는지 여부는 중요하지 않습니다. 발신자에게 영향을 미치지 않습니다. 마찬가지로, 당신은 또한이 작업을 수행 할 수 있습니다 : 당신도이 작업을 수행 할 수

// In header 
class Foo { 
void foo(int b); 
}; 

// In cpp 
void Foo::foo(const int b) { 
//Stuff 
} 

다음 INT 이후

// In header 
class Foo { 
void foo(const int b); 
}; 

// In cpp 
void Foo::foo(int b) { 
//Stuff 
} 

는 값에 의해 전달되면, const와 문제가되지 않습니다.

두 번째 예제에서는 함수가 한 형식의 포인터를 사용하지만 다른 형식의 포인터를 사용한다고 구현하므로 실패합니다.

15

처음에는 컴파일러를 약속했으나 다른 사용자는 변수를 편집하지 않을 것입니다.

두 번째 예에서는 클래스의 다른 사용자에게 변수를 편집하지 않지만 그 약속을 지키지 않았다고 약속했습니다.

또한

const bar* variable 

첫 번째 형태에서

const bar* const variable 

는, 포인터가 변경하지 않습니다

bar* const variable 

사이에 뚜렷한 차이가 있음을 유의해야하지만 당신이 가리키는 객체를 편집 할 수 있습니다. 두 번째 형식에서는 포인터를 편집 할 수 있지만 (다른 객체를 가리 키지 않음) 포인터가 가리키는 변수는 절대 편집 할 수 없습니다. 최종 형식에서는 포인터 나 포인터가 가리키는 오브젝트를 편집하지 않습니다. Reference

명시된 질문에 좀 더 명확한 설명을 추가하려면 항상 const보다 적은 것을 약속 할 수 있습니다. 아무 문제없이

Foo::func1(const int x) {} 
Foo::func2(const int* const x) {} 

:

Foo::func1(const int x) {} 
Foo::func2(const int *x) {} 

나 :

class Foo { 
    void func1 (int x); 
    void func2 (int *x); 
} 

당신은 다음과 같은 구현을 컴파일 할 수 클래스를 감안할 때. 사용자에게 변수를 편집 할 가능성이 있다고 말한 것입니다. 구현시, 컴파일러에게이 특정 구현체가 사용자에게 알려주더라도 해당 변수를 편집하지 않을 것이라고 말한 것입니다. 사용자에게 약속을 어긴 적이 없으므로 코드가 컴파일됩니다.

+0

당신의 이론이 가지고 있다고 생각하지 않습니다 : 1) "int *"를 선언하고 "const int *"를 구현하면, 예제와 같이 컴파일되지 않습니다. 2) 값으로 전달하면 const를 선언하고 const로 구현할 수 없습니다. 가치있게 전달할 때 의미가 없습니다. –

+0

예. 네가 틀렸다는데 동의한다. void f (int const *); void f (int *)와는 다릅니다. 나는 당신이 void f (int * const)를 쓰고 싶다고 생각한다. void f (int *)와 같은 서명을 가진다; 초보자를 혼동시킬 수 있으므로 예제를 변경해야합니다. –

0

앞에서는 const이 인터페이스에만 영향을 미치지 만 구현은 영향을주지 않습니다. 당신은 컴파일러에게 "이 함수 내에서 bar*의 값을 변경하지 않을 것"이라고 말하고 있습니다. 여전히 포인터가 가리키는 것을 변경할 수 있습니다. 후자의 경우 bar*을 가리키는 bar 구조를 변경하지 않는다고 컴파일러 (및 모든 호출자)에게 알리는 것입니다.

+0

마지막 문장에서 "바가 가리키는 바를 수정하지 않을 것"이라고 생각합니다. "바 *가 가리키는 바 변경"은 "바 * 새로운 가치"를 부여하는 것으로 간주 될 수 있습니다. 이는 두 번째 예에서 물론 좋습니다. –

+0

고마워요, 고쳤습니다. 대명사는 명확성의 한계입니다. –

6

this question, this questionthis question을 참조하십시오.

기본적으로 const는 함수가 포인터의 값을 수정하지 않는다는 것을 의미합니다. 포인터 내용은 const가 아니며 헤더의 서명과 동일합니다.

0

그래서 두 번째 CONST :

void Foo::foo(const bar* const); 

는 메소드 서명의 부분이 아닌가?

+1

.h 파일에 메서드를 선언하면 .cpp에 메서드가 정의됩니다.선언의 모든 것은 서명 (두 const 모두)의 일부입니다. 정의에서 선언의 의미를 깨뜨리지 않는 한 인수 유형을 더 세분화 할 수 있습니다. –

+0

@mamin : 수정하십시오. 예를 들어, "void foo (const int * const a)"함수를 선언했지만 (정의하지 않는다면) 얻은 링커 에러를보고 호출하십시오. GCC에서 누락 된 것으로보고 된 서명은 "foo (int const *)"입니다. –

+0

간단 : const를 추가/제거하면 서명에 포함되지 않습니다. 그래서 void foo (int * const); 와 void foo (int *); 참으로 똑같은 서명을 가지고 있습니까? 하지만 void foo (int const *); 와 void foo (int *); 다른 시그니처가 있어야합니다 : 매개 변수 유형에 추가 된 const가 없으며 지정된 유형이 있습니다. –

0

포인터 이외의 변수 유형으로 이해하는 것이 더 간단합니다. 예를 들어, 다음 함수 선언을 가질 수

void foo(int i); 

정의는 다음과 같을 수 있습니다

은 '내가'변수가 정의 측 const를할지 여부를
void foo(const int i) { ... } 

이 구현 세부입니다 . 이 기능의 클라이언트에게는 영향을 미치지 않습니다.

+0

나는 SO 사용자가 투표하는 방법을 모르겠다. 위의 +15로 투표 한 맨 끝에 잘못된 문장이 있고 그것을 고정하는 느낌이 들지 않는 대답입니다 (ppl은 3 개월 전에 그에게 말했습니다), -1에서이 답변은 괜찮은 것이고 훨씬 더 잘 설명되었습니다. (IMHO). 공정성을 위해 +1하는 것. –

+0

동의. 나는이 대답에 대해 왜 내가 downvoted인지 이해하지 못한다 ... –

0

포인터 자체를 처리하는 방법 (const 또는 not)이 루틴 외부의 한 비트와 관련이 없기 때문에 아마도 void Foo::foo(bar* const pBar)에 대해서는별로 신경 쓰지 않습니다. C 규칙에 따르면 pBar를 변경해도 foo 외부로 이동하지는 않습니다.

그러나 (const bar* pBar)이면 컴파일러가 호출자가 비 const 객체에 대한 포인터를 전달할 수 없기 때문에 차이가 있습니다.