2010-05-26 7 views
8

에 const를 데이터 멤버와 클래스를 사용 :다음과 같이 클래스 감안할 때 벡터

class Foo 
{ 
    const int a; 
}; 

이 가능하면 벡터에 그 클래스를 넣어? 시도 할 때, 내 컴파일러는 기본 할당 연산자를 사용할 수 없다고 알려줍니다. 내 자신을 작성하려고하지만 const 데이터 멤버가있는 클래스에 대한 대입 연산자를 작성하는 것은 불가능하다고 주변에서 인터넷 검색을합니다. 내가 발견 한 한 게시물은 "당신이 [데이터 멤버]를 const로 만든다면 그것은 당신이 할당이 처음부터 일어나기를 원하지 않는다는 것을 의미합니다." 이것은 의미가 있습니다. 나는 const 데이터 멤버들을 가진 클래스를 작성했고, 그것에 대한 할당을 결코 의도하지 않았지만, 분명히 그것을 벡터에 넣기위한 할당이 필요하다. const-correctness를 유지하는 방법이 있습니까?

+0

정확히 const 멤버가 필요한 이유는 무엇입니까? 'Foo'는 실제로 무엇입니까? – fredoverflow

답변

3

std::vector<Foo *> 포인터의 벡터를 사용하십시오. 너 혼자서 청소하는 번거 로움을 피하려면 boost::ptr_vector을 사용하십시오.

+0

좋아, 고마워. 나는 이것을 시도 할 것이다. – Max

1

편집 : 내 커피 휴식 시간 동안 내 초기 찌르고, static const int a;는 영업 이익은 초기 의견 확인 마음에있는 사용 사례에 대해 작동하지 않습니다, 그래서 나는 다시 작성하고 내 대답을 확장하고있다.

대부분의 경우 클래스의 요소를 상수로 만들려고 할 때 항상 상수이고 클래스의 모든 인스턴스에서 상수 인 상수입니다. 이 경우, 나는 const 정적 변수를 사용

class Foo 
{ 
public: 
    static const int a; 
}; 

이 적용되는 경우, 그 과제의 문제를 해결하는 것, 그래서 사람들은, 인스턴스로 복사 할 필요가 없습니다. 불행히도, OP는 OP가 염두에두고있는 경우에는 작동하지 않을 것이라고 지적했습니다.

당신은 클라이언트가 수정할 수없는 읽기 전용 값을 만들려면, 당신은 그것을 개인 멤버 변수를 만들 수 있습니다 만이 스레드의 다른 게시물 등의 const를 getter 메소드를 통해 노출을 나타냅니다 :

class Foo 
{ 
public: 
    int get_a() const { return a; } 
private: 
    int a; 
}; 

이것

class Foo 
{ 
public: 
    const int a; 
}; 

차이는 다음

  • const int은 클래스의 구현조차도 객체 수명 기간 동안 a의 값으로 머뭇 거리지 않을 것이라는 확신을줍니다. 즉, 개체가 생성 된 후에 a의 값을 수정하려고하므로 할당이 올바로 작동하지 않습니다. (이유는, a의 사본을 건너 뛰는 사용자 정의 operator=()을 쓰는 것이 아마도 설계 상 나쁜 생각 일 것입니다.)
  • 액세스가 다릅니다 – 직접 액세스하지 말고 게터를 통과해야합니다.

실제로 두 가지를 선택할 때 읽기 전용 멤버를 사용합니다. 이렇게하면 의미를 위반하지 않고 개체의 값을 다른 개체의 값으로 바꿀 수 있습니다. 당신의 경우에 그것이 어떻게 작동하는지 보겠습니다.

너비와 높이가있는 Grid 개체를 고려하십시오. 초기에 벡터를 만들었을 때 vector::reserve()을 사용하여 초기 공간을 예약한다고 가정하면 벡터는 초기 기본 초기화 (즉, 비어있는) 그리드로 채워집니다.벡터의 특정 위치를 지정하거나 벡터 끝으로 그리드를 이동하면 해당 위치에있는 객체의 값을 실제 물건이있는 격자로 바꿉니다. 그러나 당신은 이것으로 괜찮을지도 모른다! 너비와 높이를 일정하게 유지하려는 이유가 너비와 높이와 나머지 Grid 객체 내용 사이에의 일관성을 보장하고 너비와 높이가 바뀌어도 상관 없다는 것을 확인했다면 Grid의 다른 요소가 교체되기 전이나 후에, 할당의 끝까지 인스턴스의 전체 내용이 대체되고 일관된 상태로 돌아 오기 때문에이 할당은 안전해야합니다. (기본 할당 의 자성의 부족이 문제라면, 당신은 아마 복사 생성자와 swap() 작업을 사용하여 자신의 할당 연산자를 구현하여이 문제를 얻을 수 있습니다.)

요약하면, 당신에 의해 얻을 것 읽기 전용 getter를 사용하면 벡터 또는 값 의미를 가진 컨테이너의 객체를 사용할 수 있습니다. 그러나 컴파일러가 너비와 높이를 잠그지 않으므로 Grid의 내부 연산 (또는 Grid의 친구들 연산)이이 일관성을 위반하지 않도록해야합니다. 이는 기본 구성, 복사본 구성 및 할당에도 적용됩니다.

+1

변수를 정적으로 만들면 해당 클래스의 모든 인스턴스가 변수를 공유하게됩니다. 인스턴스에 고유해야하는 상수가 실제로 필요한 경우이 작업은 전혀 작동하지 않습니다. –

+0

흠, 유스 케이스를 잘못 이해했을 수도 있습니다. 이 인스턴스는 인스턴스마다 다를 필요가있는 상수입니까? 아직 그 중 하나가 필요한 경우에 나는 아직 몰랐습니다. –

+1

입니다. 필자가 작성한 프로그램에는 폭과 높이 변수가있는 Grid 클래스가 있습니다.한번 초기화 된 너비와 높이가 변하기를 원하지는 않습니다. 그래서 그것들을 일정하게 만들지 만 벡터에서 다양한 크기의 그리드를 원합니다. – Max

7

const 데이터 멤버를 사용하여 클래스를 작성 했으므로이 클래스에 대한 할당을 사용하지 않았지만 분명히이를 벡터에 배치해야합니다. const-correctness를 유지하는 방법이 있습니까? 이 제약 유형 Fooab 존재에 대한 사실이 아닌 경우

다음과 같은 제약 조건이 여전히

a = b; 
/* a is now equivalent to b */ 

을 보유하고 있는지 물어 봐야 (당신은 무엇 "해당"수단의 의미를 정의해야 !), 그러면 Foo을 표준 컨테이너에 넣을 수 없습니다. 예를 들어 auto_ptr은 해당 요구 사항을 위반하기 때문에 표준 컨테이너에 넣을 수 없습니다.

이 제약 조건을 만족하는 유형에 관해 말할 수 있다면 (예를 들어 const 멤버가 어떤 식 으로든 개체 값에 참여하지 않지만 어쨌든 정적 데이터 멤버로 만들 것을 고려한 경우) 자신의 할당 연산자

class Foo 
{ 
    const int a; 
public: 
    Foo &operator=(Foo const& f) { 
    /* don't assign to "a" */ 
    return *this; 
    } 
}; 

쓰기하지만 두 번 생각 할 수 있습니다!. 나에게, 당신의 타입이 이 아니고,이 제약 조건을 만족시키는 것처럼 보입니다!

+0

그렇다면 타입에 'a = b'를 쓰지 않을 것이라는 것을 말한다면, 아무 것도하지 않는 대입 연산자를 작성하는 것이 좋습니다. 나에게 의미가 있지만 내 타입이 그 제약 조건을 만족시키지 못한다고 생각하는 이유는 무엇입니까? -EDIT- 두 번째 생각에 나는 당신이 나아지고있는 것을 봅니다. 내 유형이 제약 조건을 충족시키지 않는다는 데 동의합니다. – Max

+1

@Max : 그건 그가 말하는 것이 아닙니다. 그는 모든 할당을 정상적으로하는 것을 말하고 있지만 const 멤버의 할당은 무시합니다. 그리고 컨테이너는'a = b'를 자유롭게 할 수 있습니다. 여러분이 할 일과 아무 관계가 없습니다. – GManNickG

0

나는 데이터 멤버 const가 아닌을 고려하고 있지만, 개인이처럼 get 함수를 통해서만 액세스 :

class Foo 
{ 
    private: 
     int a; 
    public: 
     int getA() const {return a;} 
}; 

는 CONST로이 '좋은'인가? 그것은 어떤 단점이 있습니까?

+0

데이터로 무엇을하고 있는지 알 수 없습니다. 하지만 클래스의 클라이언트가 그것을 수정할 수 없도록 원래'const' 였다면, 그렇습니다. 이것을 캡슐화라고합니다. 데이터를 비공개로 만들고 메소드를 통해 노출시킵니다. – GManNickG