에 결합 과부하 최우선 결과는 다음 코드C++ 이상한 행동
class X{
public:
virtual void foo(X x){ }
virtual void foo(int index){ }
};
class Y : public X{
public:
void foo(int index){ }
};
int main(){
Y y;
y.foo(X()); //Error, see below
}
클래스 X
을 고려 가상 foo
방법을 과부하가있다. 한 버전은 X
이고 다른 버전은 int
입니다. 이제 Y
클래스는 X
에서 상속 받고 foo(int)
메서드를 재정의합니다. foo(X)
메서드는 재정의 할 수 없으며 그대로 유지해야합니다. main
방법 형 Y
의 객체를 생성하고 foo(X)
호출시
그러나, 컴파일러는 다음의 불평 :
In function ‘int main()’:
error: no matching function for call to ‘Y::foo(X)’
note: candidate is:
note: virtual void Y::foo(int)
note: no known conversion for argument 1 from ‘X’ to ‘int’
따라서 유일한 후보는 재정의 foo(int)
방법이다. 다른 방법이 사라진 것처럼 보인다. 재정의 버전을 제거하면 Y
을 public Y : public X{};
으로 선언하면 모든 것이 정상적으로 작동합니다. 왜 이런 일이 생길까요?
왜 이가요? 이것은 기본적으로 파생 클래스가 Liskov의 원칙에 위배된다는 것을 의미합니다. 이는 C++에 대한 상당히 나쁜 디자인 결정입니다. – gexicide
@gexicide : 사실 포인터는 LSP를 위반하지 않습니다. * 포인터 나 기본 클래스에 대한 참조를 통해 *에 액세스하면 모든 기본 클래스의 메서드가 여전히 사용 가능합니다. –
@gexicide :이 언어를 결정한 이유는 기본 클래스 함수를 숨기지 않으면 예기치 않은 동작이 발생할 수 있기 때문입니다. 'X' 대신에 다른 기본 클래스의 과부하가'double'을 취했다고 상상해보십시오. 'Y' 클래스의 사용자는'Y :: foo (int)'가 호출되기를 기대하면서'y.foo (2.5)'를 호출 할 수 있습니다; 대신'X :: foo (double)'가 호출 될 것이다; 사용자가 존재할 것으로 기대하지 않는 함수. – Gorpik