8

라이브러리는 클래스에 가상 함수를 제공합니다. 라이브러리에 동적으로 링크 된 바이너리를 다시 컴파일하지 않고도이 클래스를 새로운 가상 함수로 확장 할 수 있습니까?클라이언트 코드를 재 컴파일하지 않고 가상 인터페이스를 확장 할 수 있습니까?

표준으로는 가능하지 않습니다. 이것을 허용하는 플랫폼이 있습니까?

새로운 기능이 클래스 본문의 끝에 추가되는 것이 더 쉬울까요?

+0

라이브러리 인터페이스를 확장하고 싶습니다. 기본 라이브러리 클래스를 인수로 사용하는 API 함수의 시그니처를 변경하지 않고이 작업을 수행 할 수있는 또 다른 방법이 있다면 그 사실을 알고 싶습니다. – Basilevs

+1

KDE 프로젝트의 흥미로운 문서가 있습니다 : [C++의 이진 호환성 문제] (http://techbase.kde.org/Policies/Binary_Compatibility_Issues_With_C%2B%2B). 읽으려는 다른 두 개의 문서에 대한 링크. – Mat

답변

5

표준은 바이너리 호환성과 관련이 없습니다. 그것은 클래스와 관련이 있지만 클래스의 정의를 하나의 변환 단위에서 "변경"하여 실제로 정의되지 않은 동작을 호출하는 방식입니다.

대부분의 컴파일러는 다시 컴파일 할 필요없이 많은 변경을 허용하지만 목록은 작지만 ...이 경우에는 가능하지 않을 수도 있다고 말할 것입니다. 은 파생 된 사전 지식에 따라 다릅니다. 클래스.

필자가 예상하는 문제는 컴파일러가 일반적으로 가상 테이블에서 수행하는 최적화에 있습니다.

은 사용자가 가상 ​​함수와 클래스를 만들 때, 당신이 그렇게 보이는 가상 테이블 얻을 : 파생 클래스 자신의 가상 함수는 일반적으로 "추가"일부 공간을 확보하기 위해

// B virtual table 
0 - Offset to complete object 
1 - RTTI 
2 - func0 
3 - func1 
... 

을 :

// D virtual table 
Same as B 
N+3 - func(N+1) 
N+4 - func(N+2) 

이 방법은 D 목적은 유형 (정적)을 B (포인터 또는 참조를 통해) 경우에도 그대로 사용 할 수있는 것보다, 하나의 가상 포인터를 갖는다. 당신이 D을 다시 컴파일하지 않고 B을 연장한다면

그러나, 그것은 그냥 평범한 충돌, BN+1 함수를 호출 할 때부터 대신 아마 같은 인수가없는 것 DN+1 함수를 호출 할 것이다. .. 웁스!

을 알고있는 경우을 알면 자체 클래스의 가상 함수를 추가하지 않아도됩니다.

+2

일부 라이브러리는 끝에 (일반적으로'reserved1','reserved2' 등으로 불리는) 더미 가상 함수를 추가하므로 나중에 이진 호환성을 손상시키지 않고 대체 할 수 있습니다. –

+0

@Jan Hudec : 영리한 :) 저에게 여분의 비트를 생각하게 만듭니다 ^^ –

+0

C++ 표준에는 ABI 호환성이 포함되어 있지 않습니다. 사실 그것은 동적 디스 패칭을 위해 vtable의 사용을 강제하지도 않습니다. 대부분의 (모든?) 컴파일러가 사용하는 구현 세부 사항 일뿐입니다. – rjnilsson