2009-05-20 7 views
4
class Base { 

    public: 
     void foo() const { 
      std::cout << "foo const" << std::endl; 
     } 

}; 


class Derived : public Base { 

    public: 
     void foo() { 
      std::cout << "foo"<< std::endl; 
     } 


} 

foo()constがBase用に正しく隠されていることを確認します。確かにこれは悪い考えです。おそらくBase :: foo()constをDervied :: foo()が正しくオーバーライドするようにする必要があります。—ですが、Base :: foo()を純粋に作ることはできませんバーチャル。 Base :: foo()constがDerivedで正しく隠されていることを確認する良い方法はありますか?C++の派生クラスのメソッドをオーバーライド(非表示)する方法を教えてください。

編集:Derivedで、基本実装が正しく隠されていることを確認します。

+1

"正しく隠されている"とはどういう意味ですか?関数がオーバーライドされているか、または隠されています。両方にすることはできません。 –

+0

c#overrideキーワードと同じ動作をさせる方法があるかどうか尋ねていますか?この優れたキーワードは、関数が実際に何かをオーバーライドしていることを保証します。関数のシグネチャの違いのために意図したときに、C++で何かをオーバーライドしないのは簡単な間違いです。 – markh44

+0

「隠されている」とは、公開されていないことを意味しますか? – zooropa

答えて

0

純粋な仮想にして実装を強制したくない場合は、Baseクラスの本文foo()をただちに例外をスローするようにしてください。これは、すべての実装者とユーザーがオーバーライドを実装するようにする目的、またはオーバーライドを使用しようとするときに吹き飛ばすことを目的としています。

私は以前これを行ってきましたが、少し醜いですが、それは非常に確かに機能します。

1

"void foo()const"と "void foo()"は、C++に関する限り全く異なる2つの関数です。だからあなたはBaseから "foo"を隠してDerivedの "foo"が見えないのです。

+4

これは真実ではありません。基本クラスが関数を定義している場合、それらが異なるパラメータを持っていても(同じことを試してみませんか?)、これらの関数を再び可視にする方法"using base :: foo;"を使うことです。 – Motti

4

派生クラスでメンバー関数fooを定義するだけで、すべてのfoo関数が基本クラスに隠されています。

質問を少し修正する必要があります。派生クラスのfooが基本クラスのfooの適切な置き換えではないかと心配していますか?あなたが本当に求めていることを判断しようとするのは苦労しています。

編集:編集と追加のコメントに基づいて、私はあなたがC++での隠蔽の仕組みについて誤解していると思います。この場合、ある関数がconstであり、もう1つは関数ではないということは関係ありません。C++が派生クラスで関数fooを見つけたら、他の場所での検索は止まります!これは通常、人にとって大きな罠です。以下を考慮してください:

class Base 
{ 
    void foo(double d) 
    { 
     cout << d; 
    } 
}; 
class Derived : public Base 
{ 
    void foo(int i) 
    { 
     cout << i; 
    } 
}; 

Derived obj; 
obj.foo(123.456); 

出力はどのようなものですか?それは123です!そしておそらく、二重の値が切り捨てられることを伝えるコンパイラの警告が出てきます。関数のシグネチャが2倍の場合でも、より良い一致が見られますが、それは決して考慮されません。隠されています。

+0

質問を編集しました – kal

1

Baseからfoo()を隠してもよろしいですか?多態性を利用するには、foo()の基本バージョンを仮想化する必要があります。しかし、純粋である必要はありません。それ以外の場合は、静的バインディングが必要ですか?

0

私があなたの質問を正しく理解していれば、クラスがメソッドを強制的にオーバーライドする方法を尋ねています。Baseクラスでメソッドを純粋にする必要はありません。

派生クラスのすべてがメソッドの実装を提供するようにすることで、IMHOではBaseクラスのメソッドがどのような目的でも実際に使用されていないことを暗示しています。オブジェクトはDerivedクラスのバージョンfoo()のいずれかを呼び出さなければなりません。したがって、この方法は私の意見では純粋なバーチャルにする必要があります。私はこれを達成するための他の方法はないと思います。

また、foo()の署名をBaseDerivedに変更しました。これにより、クラスメソッドはDerivedクラスで非表示になります。 using Base::fooを使用しない限り、方法foo()Derivedクラスには表示されません。ベースで

0

:: FOO()、あなたは次のことを行うことができますが:

assert (dynamic_cast<const Derived*> (this) == NULL); 

しかし、それは三つの問題がある:それは閉鎖されるべき基本クラスの変化を必要と

  1. を変更に。
  2. Base :: foo()をBaseオブジェクトから明示的に、または明示的に呼び出すことが必要な場合があるので、必要以上に強くなる可能性があります。
  3. これはRTTIを使用します。これはvtblを意味します。なぜなら、ユーザーの仮想関数を最初に使用したくなかったのかもしれないからです。
関連する問題