2009-09-12 4 views
1

왜 vtable을 검사 할 언어가 지원되지 않는 이유가 무엇입니까? 왜 멤버 함수를 새 함수로 바꿀 수 없습니까? 그러한 기능을 잘 활용할 수있는 방법이 있다는 느낌이 들었습니다.왜 C++ 상속 메커니즘이 불투명합니까?

내가 그런 일을 할 수있게 해주는 다른 언어가 있습니까?

+3

저는 vtable을 사용하는 것이 더 읽기 쉽고 안전하고 신뢰할 수있는 코드가되지 않을 것이라고 확신합니다. – Bombe

+0

언어 지원이있는 경우이를 "장난"이라고 생각하지 않습니다. 이것은 분명히 이해되고 널리 사용되는 프로그래밍 실습이 될 것입니다. –

+0

그래,하지만 그렇지 않아, 그래서 ... –

답변

5

주된 이유는 vtable을 구현 세부 사항으로 유지하면 모든 구체적인 구현을 통해 최적화 된 상태로 최적화 할 수 있다는 것입니다. 이는 예를 들어, 주어진 메소드 (또는 모든 메소드)에 가상 호출이 없다는 것을 증명할 수 있다면 vtable 전체를 다듬거나 제거 할 수도 있습니다. 또는 vtable 디스패치를 ​​if-else 유형 검사로 대체 할 수 있습니다 (예 : 그것은 단지 몇 가지 대안이 있음을 봅니다 (이것은 분기 예측이이 경우에는 작동하지만 vtable에서는 작동하지 않으며 if-else 분기가 인라인 될 수 있기 때문에 유리할 수 있습니다). vtable에서 메서드를 재정렬하여 가장 일반적으로 호출되는 메서드를 이전에 호출하거나 일반적으로 호출되는 메서드를 vtable의 인접 슬롯에 채워 캐싱을 활용할 수 있습니다. 등등. 물론 모든 구현은 vtable 레이아웃을 완전히 예측할 수 없게 만들고 따라서 언어 스펙에 따라 구현에 노출 될 경우 유용하지 않습니다.

또한 vtable은 소리가 나는 것처럼 간단하지 않습니다. 예를 들어, 컴파일러는 종종 가상 상속이나 공변 반환 유형과 결합 된 다중 상속에 대한 포인터 this 포인터를 수정하기 위해 썽크를 생성해야합니다. 이것은 다시 한번 "최선의 방법"이 없기 때문에 (다른 컴파일러가 다르게하는 이유이기도합니다), 표준화하면 특정 방식으로 효과적으로 해결해야합니다.

즉, "vtable 전환"은 상위 수준 구조로 노출 될 경우 잠재적으로 유용한 기술이므로 최적화가 여전히 가능합니다. 예를 들어, 하나의 클래스 (하나의 디폴트, 다른 이름의 클래스)에 대해 몇 가지 states을 정의하고 이름이 지정된 상태의 일부 메소드를 오버라이드 할 수있게 해주는 UnrealScript를 참조하십시오. 파생 클래스는 기존 상태의 메서드를 더 오버라이드하거나 자체 상태를 추가하고 오버라이드 할 수 있습니다. 또한 상태는 다른 상태를 확장 할 수 있습니다 (특정 상태에 대해 메서드를 재정의하지 않으면 해당 상태가 "부모"상태로 되돌아가는 등 체인이 기본 상태가 될 때까지 계속됩니다). 액터 모델링 (본질적으로 게임 임)의 경우이 모든 것이 많은 의미가 있습니다. 이것이 UnrealScript가 가지고있는 이유입니다. 그리고이 모든 것에 대한 효율적인 구현 메커니즘은 vtable 전환이며, 각 상태는 별도의 vtable입니다.

17

컴파일러의 구현 세부 사항이기 때문에. 이 구현은 변경 될 수 있으며이를 기반으로하는 코드는 기껏해야 허약합니다.

8

C++는 사용하지 않는 것에 대해 '지불하지 않는'언어입니다. 이런 종류의 런타임 지원은 그 철학과는 반대로 실행됩니다.

이를 지원하는 많은 언어가 있습니다 (스펙트럼의보다 역동적 인 끝).

+0

이 문제를 지원하는 언어를 알려주십시오. 내 머리 속의 음성은 JavaScript와 Python을 말합니다. 그러나 확실하지는 않습니다. –

+0

JavaScript 나 Python에서 지원되는지 여부는 명확하지 않지만 Ruby에서 지원하는 것이 가장 확실합니다. –

+0

정말 강력한 오브젝트 시스템은 'CLOS'와 'MOP'을 찾는다. – gimpf

8

보통은 그렇지만 VTable으로 구현할 필요가 없기 때문에. 간단히 말해 C++에 VTable 같은 것이 없습니다!

3

JavaScript, Python 및 Ruby 모두이 작업을 수행 할 수 있습니다. 이러한 언어에서 클래스 및 인스턴스 정의는 런타임에 변경할 수 있습니다. 추상적으로, 각 객체 및 유형은 검사 및 업데이트 할 수있는 멤버 변수 및 메소드 사전입니다.

생성 된 바이너리 코드를 다시 작성할 필요가 있으므로 상당한 성능 비용이 들기 때문에 C++에서는 불가능합니다.

2

나는 파이썬 같은 동적 언어에 그런 일을 할 수 있다고 생각 :

>>> class X(): 
...  def bar(self): print "bar" 
...  
>>> x = X() 
>>> x.bar() 
bar 
>>> def foo(x): print "foo" 
... 
>>> X.bar = foo 
>>> x.bar() 
foo 

C++와 같은 정적 언어의 차이는 인터프리터가 런타임에 모든 이름을 검색한다는 것입니다 후 무엇을 결정한다.

C에서

++에 대한 가능성이 다른 솔루션이 있습니다 함수 포인터를 사용 할 수있는 간단한있는 문제 "서로 멤버 함수를 대체"

#include <iostream> 

class X; 
typedef void (*foo_func)(const X&); 

void foo(const X&) { std::cout << "foo\n"; } 
void bar(const X&) { std::cout << "bar\n"; } 

class X 
{ 
    foo_func f; 
public: 
    X(): f(foo) {} 
    void foobar() { f(*this); } 
    void switch_function(foo_func new_foo) { f = new_foo; } 
}; 

int main() 
{ 
    X x; 
    x.foobar(); 
    x.switch_function(bar); 
    x.foobar(); 
} 

(foo는 바는 X를 사용하지 않는 이 예제에서 파이썬 예제와 비슷한 & 인수입니다.

1

vtable을 노출하는 정적으로 컴파일 된 언어에서 작업 중이며 실제로는 hair이 노출 될 것으로 생각됩니다.

3

Vtable은 특정 상황에서만 일부 컴파일러에 존재합니다 (즉, 표준에 지정되어 있지 않지만 구현 세부 사항). 존재할지라도 가상 함수가 있고 다형성을 구현하기 위해 간접 참조가 필요할 때만 발생합니다. 이 작업이 필요하지 않은 경우 최적화 할 수 있으므로 호출시 간접 비용을 줄일 수 있습니다.

슬프게도 (그렇지 않으면 문제에 대한 견해에 따라 ;-) C++은 원숭이 패치를 지원하도록 설계되지 않았습니다. 경우에 따라 (예 : COM) vtable은 구현의 일부이므로 배후에서 엿볼 수 있습니다. 그러나 이것은 결코 지원되거나 이식되지 않습니다.

1
  • C++로 수행 할 수있는 모든 작업은 약간의 팔꿈치 그리이스로 직선 C로 수행 할 수 있습니다.
  • 겸손하고 합리적인 C 프로그램은 C++로 컴파일해야합니다.

아마도 C++의 기본 제공 기능을 사용하지 않고 자신의 vtable을 구현하는 것이 좋습니다. POTMF (pointer-to-member-function)를 사용하면 많은 재미를 느낄 것입니다!

vtable 인트로 스펙 트를 사용하여 컴파일 된 언어를 찾는 데 어려움이 있습니다. 구현이 쉽지 않기 때문입니다. 그러나 인터프리터 언어의 경우 상황은 다른 방향입니다.

0

다른 사람들도 지적했듯이 C++ 표준에는 "vtable"이라는 개념이 없습니다. 이는 이름 변환과 마찬가지로 거의 보편적 인 구현 기술이기 때문입니다.

컴파일 된 언어로 함수를 즉시 재정의 할 수있는 기능이 필요한 경우 Common Lisp에 관심이있을 수 있습니다. 다른 언어가 있어야합니다. 그러나 생각할 수있는 유일한 언어는 정적 상속과 함수이거나 성능면에서 큰 비용으로 해석됩니다.

1

거기에 다른 언어가 있습니까? 가지를 허용 할 수 있습니까?

Objective-C (및 Objective-C++도 마찬가지 임)는 이미 컴파일 된 메소드의 런타임 대체를 허용합니다. 그것은 당신이 누구에게 물어 보느냐에 따라 정적 기법과 동적 기법 중 가장 좋은 조합이거나 최악입니다.