2012-02-11 3 views
1

STL 소스 (DinkumWare, SGI, STLport 등)를 파고 구현 선택에 대한 이해를 시도하는 동안 (내가 잘 진행되고 있음), 조금 이상하거나 오히려 전에 결코 흘러 가지 않는 ive.상속, 의사 다형성

일반적으로 파생 클래스에서 멤버 함수를 오버로드하려면 기본 클래스 멤버 함수 시그너처 앞에 가상 키워드를 추가합니다. 그러나 STL 소스의 여러 지점에서는 그렇지 않습니다.

template <typename T> class A { 
public: 
    void func() { std::cout << "inside A func()" << std::endl; } 
}; 

template <typename T> class B : public A<T> { 
public: 
    void func() { std::cout << "inside B func()" << std::endl; } 
}; 

컴파일러는 내가 라인을 따라 오류 뭔가를 기대 한대로이 의사 다형성과 잘 보인다 여기

내가 STL 구현에보고하고있는 무슨의 컷 다운 버전입니다 of :

error C2535: 'void B<T>::func(void)': member function already defined or declared 

여기에 무슨 일이 일어나고 있는지 설명 할만큼 친절한 사람이 있습니까?

추신 : 이것은 또한 클래스가 템플릿이 아니더라도 작동하는 것 같습니다.

은 '

답변

2

virtual 키워드가 없으면 - 함수를 다시 정의 할 때 수퍼의 함수가 숨겨집니다.

func()을 다시 표시하면 A과는 다른 B에 대한 새로운 기능이 컴파일러에 있음을 알 수 있습니다. 이 virtual을 선언하지 않기 때문에

비록, 당신은 당신이 typeB의 변수에서 func()를 호출하는 경우에만이 영향을 볼 수 있습니다. B을 보유하는 A 유형의 변수는 A의 func()를 호출합니다.

A *a = new B; 
a->func() 

은 첫 번째 [A] 메소드를 호출합니다.

하는 B의 메소드를 호출하려면 B로 유형을 필요가

B *b = new B; 
b->func() 
2

B<T>::func 멤버 단순히 shadowsA<T>::func 안부. p->func()으로 전화 할 때 이 B<T>을 가리키는 경우 A<T>::func이 호출되므로 다형성이 없습니다. std::ifstream::rdbufhides its ancestor's method by that name을 실제로 그것의 반환 형식이 변경됩니다 : C++ 표준에서

#include <iostream> 

struct A 
{ 
    void func() { std::cout << "Hello!\n"; } 
}; 

struct B : public A 
{ 
    void func() { std::cout << "Goodbye!\n"; } 
}; 

int main() 
{ 
    B b; 
    A *p = &b; 

    p->func(); 
    b.func(); 
} 

(Demo)

이 그림자/이름 숨기기 악용 적어도 한 곳이있다.

+0

감사합니다, 당신은 매일 새로운 것을 배웁니다! 이제는 그것이 합리적이라고 언급했습니다. – rtlayzell

1

이러한 기능이기 때문에 분명히 오류가없는 단지 오버로드 : A::func()A 객체 (참조 또는 복용 서명이 포인터)를 제 1 인수로서 취하는 한편, B::func()B 오브젝트를 제 1 인수로서 취하는 서명을 갖는다. 즉, 이것은 인수가 다르지만 함수 이름이 두 개인 함수의 오버로드 일뿐입니다.

이것은 다른 함수로 본질적으로 포워딩하는 함수와 다른 리턴 유형을 생성하기 위해 몇 군데에서 수행됩니다 (적어도 이것들은 내가 생각할 수있는 곳입니다). 실제로는 다른 어떤 것보다 혼란 스럽지만 사용자의 삶을 조금 더 쉽게 만들어주는 것입니다. 생각할 수있는 예 (예 : 스트림의 rdbuf() 함수)는 대신 다른 이름을 만들어야합니다.

1

허용되는 코드입니다. B<T>::func은 단지 A<T>::func을 숨기고 있습니다.

A<int> a; 
B<int> b; 
a.func(); // inside A 
b.func(); // inside B 

A<int> *const pA = new B<int>(); 
pA->func(); // inside A 

다형성 형태 func 통해 호출, 상기 포인터의 타입의 함수를 호출한다.