2011-09-12 19 views
1

このクラスは、Aから派生したクラスBです。両方ともf()と宣言しています。 fは保護されています。したがって、fはAの内部とBの内部でのみ呼び出されます。 f()は仮想として宣言する必要がありますか?保護された機能のために仮想が不要

Cは、Bに由来し、Aに由来します。 BおよびAは、保護された非仮想保護を宣言するf()です。 CBf()へのコールは、B::f()とAに解決されますか?

この場合、保護されたメンバーが静的な解決を行うためには常に仮想を避けるべきですか?これは自動的に行われますか?ありがとう!

+2

散文の代わりにコードで書いた方が良いでしょう。 – PlasmaHH

+0

興味のあるもの:http://www.gotw.ca/publications/mill18.htm – Flexo

答えて

1

ポリモフィックな動作(この例はTemplate Method pattern)を使用する場合は、保護されたメソッドvirtualを宣言する必要があります。これは避けるべきです。しかし、後者の場合、サブクラスで同じシグネチャを持つ別の関数で関数をシャドーするべきではありません。そうしないと、微妙なバグの可能性を開くような不思議な振る舞いをします。

+0

この場合の多態性とは何ですか?基本クラスへのポインタを持つと仮定していませんか?これは定義上、公共の機能へのアクセスを必要としませんか? – Cookie

+0

@Cookieいいえ、あなたがAから(外部から)呼び出すか、CまたはBで再実装/オーバーロードされていないすべての関数で、 'this'はAへのポインタです。呼び出されたメソッドが仮想でない場合は、実行時に解決されず、Aメソッドを取得します。 –

+0

@Cookie、いいえ、パブリックアクセスは必要ありません。 Aで宣言され、異なるサブクラスでオーバーライドされた 'protected virtual'メソッドを呼び出す' A'のパブリックメソッドを考えてみましょう。 'protected'メソッドを使って多態的な動作を取得します。詳細については、* Template Method *のリファレンスを参照してください。 –

0

として、私は私のCの上に少しさびてい++が、私はあなたが方法privateを宣言ので、あなたが一緒にあなたのシナリオでprotectedvirtualを必要とするとき、「静的な解像度は」のみ保証されるだろうと言うでしょう...

+1

あなたは実際に[プライベート仮想関数](http:// stackoverflow。com/questions/2170688/private-virtual-method-in-c)を使用すると、動的にバインドされます。 JavaとC#のIIRCでは、秘密鍵は実際には無効化できないため、静的にバインドされています。 – eran

2

f()への呼び出しがAから派生した関数(BまたはCにオーバーロード/再実装されていない)で行われる限り、thisポインタはA*に解決され、したがってA::f()が呼び出されます。そうではありませんが、この場合は仮想関数が必要です。

0

ので:

class A { 
public: 
    void f() { std::cout << "A::f\n"; } 
}; 

class B : public A { 
public: 
    void f() { std::cout << "B::f\n"; } 
}; 

限り、コンパイラはオブジェクトが実際にBであることを知っているとして、それは(Fを呼び出します)B.におけるしかし、これは必ずしもそうではありません。

void callF(A* a) 
{ 
    a->f(); 
} 

B b; 
callF(&b); // prints A::f 

callFなどの関数で正しいf()関数を呼び出す場合は、virtualにします。一般的に、子孫クラスで関数をオーバーライドするのが理にかなっている場合、関数を仮想にします。これは保護された機能の場合によく見られます。

+0

申し訳ありませんが、この例は 'f()'が公開されていることを前提としています。 – Cookie

関連する問題