2009-10-22 6 views
4

특정 클래스의 특정 순서로 특정 구조체의 벡터를 정렬하려고합니다. 클래스의 struct 및 predicate 함수에 대한 정의를 작성하고 이러한 struct 및 함수를 사용하여 클래스의 메서드에서 std :: sort를 실행했습니다. 그러나 컴파일 오류가 발생했습니다. gcc 버전은 4.0.1이고 OS는 Mac OSX입니다. 코드는 다음과 같습니다.클래스에서 술어 함수로 C++ std :: sort

class sample { 
public: 
    struct s { 
    int x; 
    int y; 
    }; 

    bool cmp (struct s a, struct s b) { 
    if (a.x == b.x) 
     return a.y < b.y; 
    else 
     return a.x < b.x; 
    } 

    int func(void) { 
    std::vector <struct s> vec; 

    // ... 

    sort(vec.begin(), vec.end(), cmp); // compilation error 

    // ... 

    return 0; 
    } 
}; 

int main(void) { 
    sample *smp = new sample(); 
    smp->func(); 
    return 0; 
} 

오류 메시지는 매우 복잡하고 복잡합니다. 그래서 이것은 그것의 처음 두 줄입니다.

sortSample.cpp: In member function 'int sample::func()':
sortSample.cpp:51: error: argument of type 'bool (sample::)(sample::s, sample::s)' does not match 'bool (sample::*)(sample::s, sample::s)'
...

위의 방법 대신 다음 방법으로 코드를 올바르게 실행할 수 있습니다.

  1. class sample 및 기능의 struct scmp() 외부를 정의한다.
  2. 함수 cmp()을 제거하고 <의 연산자 오버플로를 struct s에 정의하십시오.

각 접근법의 샘플 코드는 다음과 같습니다.

1)

struct s { 
    int x; 
    int y; 
}; 

bool cmp (struct s a, struct s b) { 
    if (a.x == b.x) 
    return a.y < b.y; 
    else 
    return a.x < b.x; 
} 

class sample { 
// ... 

2)

struct s { 
    int x; 
    int y; 

    bool operator<(const struct s & a) const { 
    if (x == a.x) 
     return y < a.y; 
    else 
     return x < a.x; 
    } 
}; 

이 사람이 행동의 메커니즘을 알 수 있습니까? 왜 처음 접근하면 컴파일 오류가 발생합니까?

감사합니다.

답변

12

첫 번째 경우 cmpclass sample의 멤버 함수로 선언되므로 호출하려면 this 포인터가 필요합니다. 포인터가 사용 가능하지 않기 때문에 컴파일러는 그것에 대해 불평하고 있습니다. 정적 함수는이 포인터를 호출 할 필요가 없기 때문에 cmpstatic 함수로 선언하여 작동하게 만들 수 있습니다. 두 번째 경우에는 cmp가 독립 실행 형 함수로 다시 선언되므로 다시 정적 함수와 동일하게 동작합니다. 세 번째 경우 (오버로드 된 연산자 사용)에서는 정렬 알고리즘이 벡터의 각 객체에 대한 함수를 호출하므로 컴파일됩니다.

6

cmp은 샘플의 특정 인스턴스와 관련이 없으므로 정적 멤버 함수로 만듭니다.

5

연산자()를 사용하여 귀하의 가능성에 표시 할 수있는 세 번째 방법 : 당신이 필요로 할 때 당신은 단지 함수를 멤버 함수를해야하기 때문에, 나는 클래스 외부 cmp를 정의하는 생각

bool operator() (const s& a, const s& b) const 
{ 
    if (a.x == b.x) 
     return a.y < b.y; 
    else 
     return a.x < b.x; 
} 

sort(vec.begin(), vec.end(), *this); 
+0

와우, 이것은 대단한 트릭입니다. 감사! 이것은 비교 연산자가 비교할 두 객체와 함께 클래스 인스턴스의 멤버에 액세스 할 수있는 유일한 방법이었습니다. 제 경우에는 비교 된 객체가 상대적 인 32 비트 인덱스를 사용할 수 있기 때문에 실제로 도움이되었습니다. 64 비트 포인터. – Deadcode

+0

sort()를 호출하는이 메서드는 참조 또는 포인터가 아닌 * this 복사본을 전달하므로이 트릭을 사용하는 경우 복사본에 조건부에 필요한 멤버 만 포함되는지 확인하십시오. 비트 또는 64 비트 멤버 (필요한 경우 "this"의 상속 및 형 변환 사용). – Deadcode

+0

또한 * this의 복사본은 sort()에 전달 될뿐만 아니라 사용중인 STL 구현에 따라 sort() 유틸리티 함수로 재귀 적으로 전달되기도합니다. – Deadcode

0

최선을 클래스의 일부 개인 기능에 액세스 할 수 있으며, 논리적으로는 해당 기능이 제대로 작동한다고 느낍니다. cmp은 구현을위한 기능을 클래스 sample에 제공하는 유틸리티 함수이지만 실제로는 비공개 멤버에 액세스 할 필요는 없습니다. 게다가 그것은 객체의 컨텍스트 내에서 호출되지 않을 것입니다 (그것의 유일한 연산은 그것의 매개 변수에서 작동합니다, 포인터에는 아무 것도 없습니다). 또한 클래스 sample::cmp의 컨텍스트에서 호출되어야합니다.평범하지 않은 것처럼 보일 수도 있지만 일반적으로 불필요한 액세스 범위에서 기능이나 코드를 제공하면 소프트웨어 버그 나 디자인 컨볼 루션의 원인이 될 수 있습니다.

위의 작업을 수행하면 추가로 std::sort을 호출 할 수 있으므로 질문에 대한 답변을 얻을 수 있습니다.

관련 문제