태그 보관물: c++-faq

c++-faq

멤버 액세스 연산자 과부하->,. * 멤버 액세스 연산자를 제외한 대부분의 연산자 오버로딩을

나는, 멤버 액세스 연산자를 제외한 대부분의 연산자 오버로딩을 이해 ->, .*, ->*

특히,이 연산자 함수로 전달되는 것은 무엇이고 무엇을 반환해야합니까?

운영자 기능 (예 operator->(...):)은 어떤 멤버가 참조되고 있는지 어떻게 알 수 있습니까? 알 수 있습니까? 심지어 알아야합니까?

마지막으로 고려해야 할 const 고려 사항이 있습니까? 예를 들어과 같은 것을 오버로드 할 때는 operator[]일반적으로 const 버전과 non-const 버전이 모두 필요합니다. 멤버 액세스 연산자에는 const 및 non-const 버전이 필요합니까?



답변

->

이것은 정말 까다로운 유일한 것입니다. 비 정적 멤버 함수 여야하며 인수를 사용하지 않습니다. 반환 값은 멤버 조회를 수행하는 데 사용됩니다.

리턴 값이 포인터가 아닌 클래스 유형의 다른 오브젝트 인 경우 후속 멤버 검색도 operator->함수에 의해 처리됩니다 . 이것을 “드릴 다운 동작”이라고합니다. 언어 operator->는 마지막 호출이 포인터를 반환 할 때까지 호출을 연결합니다 .

struct client
    { int a; };

struct proxy {
    client *target;
    client *operator->() const
        { return target; }
};

struct proxy2 {
    proxy *target;
    proxy &operator->() const
        { return * target; }
};

void f() {
    client x = { 3 };
    proxy y = { & x };
    proxy2 z = { & y };

    std::cout << x.a << y->a << z->a; // print "333"
}

->*

이것은 특별한 것이 없다는 점에서 까다 롭습니다. 비 오버로드 버전은 클래스 왼쪽에 유형과 오른쪽에 멤버 유형 포인터의 객체에 대한 포인터의 객체를 필요로한다. 그러나 과부하가 걸리면 원하는 인수를 취하고 원하는 것을 반환 할 수 있습니다. 비 정적 멤버 일 필요도 없습니다.

즉, 이와 같은 단지 일반적인 이진 연산자 +, -/. 참조 : 무료 연산자-> * 과부하가 악한가?

.*.

오버로드 할 수 없습니다. 왼쪽이 클래스 유형일 때 이미 내장 된 의미가 있습니다. 어쩌면 왼쪽에 포인터로 정의 할 수있는 것이 다소 합리적이지만 언어 설계위원회는 유용하다고 생각하는 것이 더 혼란 스럽다고 결정했습니다.

오버로드 ->, ->*, ., 및 .*표현이 정의되지 않은 될 경우에만 경우에 입력 할 수 있습니다, 그것은 전혀 오버로드로 유효한 것입니다 표현의 의미를 변경하지 않을 수 있습니다.


답변

연산자->는 특별합니다.

“비정형적인 추가 제약이 있습니다. 포인터 역 참조 연산자가있는 객체 (또는 객체에 대한 참조)를 반환하거나 포인터 역 참조 연산자 화살표가 가리키는 항목을 선택하는 데 사용할 수있는 포인터를 반환해야합니다. ”
Bruce Eckel : Thinking CPP Vol-one : 운영자->

편의를 위해 추가 기능이 제공되므로 전화하지 않아도됩니다.

a->->func();

간단하게 할 수 있습니다 :

a->func();

따라서 연산자->가 다른 연산자 과부하와 다릅니다.


답변

멤버 액세스를 오버로드 할 수 없습니다 .(예 : 두 번째 부분 ->). 그러나 단항 역 참조 연산자 *(즉, 작업의 첫 번째 부분)에 과부하를 걸 수 있습니다 ->.

는 C ++ ->연산자는 기본적으로 두 단계의 결합이며, 당신이 생각하면이 분명하다 x->y동일합니다 (*x).y. C ++을 사용하면 클래스의 인스턴스 일 (*x)때 파트 로 수행 할 작업을 사용자 정의 할 수 있습니다 x.

->오버로드 의 시맨틱 은 다소 이상하다. C ++에서는 (포인팅 된 객체를 찾는 데 사용될) 일반 포인터를 반환하거나이 클래스가 ->연산자를 제공하는 경우 다른 클래스의 인스턴스를 반환 할 수 있기 때문에 다소 이상하다 . 이 두 번째 경우에는 참조 해제 된 객체에 대한 검색이이 새 인스턴스에서 계속됩니다.


답변

->지적되는 내용 회원 모르는 연산자, 그것은 단지의 실제 멤버 액세스를 수행하는 객체를 제공합니다.

또한 const 및 non-const 버전을 제공 할 수없는 이유가 없습니다.


답변

연산자-> () (여기에 인수가 전달되지 않음)를 오버로드 할 때 컴파일러가 실제로하는 일은 유형에 대한 실제 포인터를 반환 할 때까지 재귀 적으로 호출하는 것입니다. 그런 다음 올바른 멤버 / 방법을 사용합니다.

예를 들어 실제 포인터를 캡슐화하는 스마트 포인터 클래스를 만드는 데 유용합니다. 오버로드 된 operator->가 호출되고 수행하는 모든 작업 (예 : 스레드 안전을위한 잠금)이 수행되고 내부 포인터를 반환 한 다음 컴파일러가이 내부 포인터에 대해->를 호출합니다.

constness에 관해서는-의견과 다른 답변에 답변되었습니다 (둘 다 제공 할 수 있고 제공해야합니다).


답변