2012-02-11 15 views
1

STLソース(DinkumWare、SGI、STLportなど)を掘り下げ、実装の選択肢を理解しようとしている間に、私は少し奇妙な感じがするむしろ以前は決して動かない。継承、疑似多型

一般に、派生クラスのメンバ関数をオーバーロードしたい場合は、基本クラスメンバ関数のシグネチャの先頭にvirtualキーワードを付加しますが、STLソースのさまざまな時点でそうではありません。ここで

は、私は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; } 
}; 

コンパイラは、私は線に沿って、エラー何かを期待していたとして、この疑似多形、と罰金ですof:

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

誰かがここで何が起こっているのか説明するのに十分親切でしょうか?

PS:これもテンプレートがクラスなしで動作するようです。

は「

答えて

2

virtualキーワードがない - 関数を再定義するときは、スーパーの関数が隠れています。

func()を再編集すると、Aのものとは異なるBの新しい機能がコンパイラに伝えられます。それはvirtualを宣言されていないので、

けれども、あなたはtypeBの変数からfunc()を起動する場合にのみ、この影響を与える表示されます。 Bを保持するタイプAの変数は、Aのfunc()を呼び出します。

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

は、最初の[A]メソッドを呼び出します。

Bのメソッドを呼び出すには、あなたがBするタイプのものが必要です。A::func()は、参照(Aオブジェクトを取って署名を持っているか:これらの機能は、単にオーバーロードされているので

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

あり、明らかにエラーではありませんポインタ)を第1引数とし、B::func()Bオブジェクトを第1引数とする署名を有する。つまり、これは引数の異なる2つの関数を関数名でオーバーロードしているだけです。

これは、いくつかの場所で行われ、関数とは異なる戻り型を生成します。これは、本質的に別の関数に転送されます(少なくとも、私は考えることができる場所です)。これは、実際には他の何よりも混乱していますが、ユーザーの生活を少し楽にすることです。考えられる例(例:ストリーム内の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を呼び出し、それがポインタの型で関数を呼び出します。