왜 ‘.’를 오버로드 할 수 없습니까? C ++의 연산자? ++에서 연산자를 사용하고 개체에 대한 참조를 반환합니다. 당신은

.NET Framework를 오버로드 할 수 있으면 매우 유용 할 것입니다. C ++에서 연산자를 사용하고 개체에 대한 참조를 반환합니다.

당신은 오버로드 할 수 operator->operator*하지만operator.

이에 대한 기술적 이유가 있습니까?



답변

Bjarne Stroustrup의이 인용문을 참조하십시오 .

운영자 . (점)은 원칙적으로->에 사용 된 것과 동일한 기술을 사용하여 오버로드 될 수 있습니다. 그러나 이렇게하면 작업이 개체 오버로딩을위한 것인지에 대한 질문으로 이어질 수 있습니다. 또는에서 참조하는 객체. 예를 들면 :

class Y {
public:
    void f();
    // ...
};

class X {    // assume that you can overload .
    Y* p;
    Y& operator.() { return *p; }
    void f();
    // ...
};

void g(X& x)
{
    x.f();    // X::f or Y::f or error?
}

이 문제는 여러 가지 방법으로 해결할 수 있습니다. 표준화 당시에는 어떤 방법이 가장 좋은지 분명하지 않았습니다. 자세한 내용은 The Design and Evolution of C ++를 참조하십시오 .


답변

Stroustrup은 C ++는 확장 가능해야하지만 변경 가능한 언어는 아니어야한다고 말했습니다.

도트 (속성 액세스) 연산자가 언어의 핵심에 너무 가까워서 오버로딩을 허용하지 않는 것으로 나타났습니다.

참조 디자인 및 C의 진화 ++ , 242 페이지, 섹션 11.5.2 스마트 참조를 .

operator의 과부하를 허용하기로 결정했을 때 ->자연스럽게 operator. 가 비슷하게 오버로드 될 수 .

그 당시 나는 다음과 같은 주장이 결정적이라고 생각했다. If objis a class object then obj.mhas a meaning for every member mof the object ‘s class. 우리는 내장 연산을 재정의함으로써 언어를 변경 가능하게 만들지 않으려 고합니다 (비록 =절박하고 단항의 경우 규칙을 위반하지만 &).

.클래스 에 대한 오버로드를 허용하면 정상적인 방법으로의 X멤버에 액세스 할 수 없습니다 X. 우리는 포인터를 사용해야 ->하지만, ->&도 다시 정의되어있을 수 있습니다. 나는 변경 가능한 언어가 아닌 확장 가능한 언어를 원했습니다.

이러한 주장은 중요하지만 결정적이지는 않습니다. 특히 1990 년에 Jim Adcock은 운영자가 . 정확히 운영자 와 똑같은 방식으로 운영자의 과부하를 허용하도록 제안했습니다 ->.

이 인용구의 “I”는 Bjarne Stroustrup입니다. 당신은 그것보다 더 권위있을 수 없습니다.

C ++를 정말로 이해하고 싶다면 ( “왜 이런 식입니까”)이 책을 반드시 읽어야합니다.


답변

Stroustrup 은이 질문에 대한 답을 가지고 있습니다 .

운영자 . (점)은 원칙적으로->에 사용 된 것과 동일한 기술을 사용하여 오버로드 될 수 있습니다. 그러나 이렇게하면 작업이 개체 오버로딩을위한 것인지에 대한 질문으로 이어질 수 있습니다. 또는에서 참조하는 객체. 예를 들면 :

class Y {
public:
    void f();
    // ...
};
class X {   // assume that you can overload .
    Y* p;
    Y& operator.() { return *p; }
    void f();
    // ...
};
void g(X& x)
{
    x.f();  // X::f or Y::f or error?
}

이 문제는 여러 가지 방법으로 해결할 수 있습니다. 표준화 당시에는 어떤 방법이 가장 좋은지 분명하지 않았습니다. 자세한 내용은 D & E를 참조하십시오 .


답변

연산자 함수 호출의 내부 메커니즘을 살펴보면 이해하기가 매우 쉽습니다. 클래스 콤플렉스는 실수 부분에 대해 두 개의 멤버 r과 허수 부분에 대해 i를 가질 수 있다고 가정 해보십시오. 말 복잡한 C1 (10, 20), C2 (10,2)을 // 우리는 클래스 내에서 이미 두 개의 인수 생성자가 가정합니다. 이제 C1 + C2 를 문으로 작성하면 컴파일러는 복소수에서 + 연산자의 오버로드 된 버전을 찾으려고합니다. 이제 우리는 내가 + 연산자를 오버로드한다고 가정하므로
C1 + C2는 내부적으로 c1.operator + (c2) 로 번역됩니다.
이제 당분간 ‘.’을 오버로드 할 수 있다고 가정합니다. 운영자. 이제 다음 호출 C1.disp () // 복잡한 객체의 내용 표시 이제 내부 표현으로 표현해보십시오.
C1.operator. (——) , 완전히 지저분한 일이 만들어졌습니다. 이것이 우리가 ‘.’를 오버로드 할 수없는 이유입니다. 운영자