2012-01-03 12 views
1

Javaの観点からは、virtualキーワードを持つ基本メソッドのみをオーバーライドできることに驚きました。 Javaでは、finalキーワードを使用して、メソッドをオーバーライドできないことを宣言します。C++でのルールのオーバーライド

私は自分の頭で、上書きを禁止することはめったにないと思っていました。そのため、誰かがあなたのクラスをどのようにフィットさせるかを拡張できるようになりました。

C++では、ある段階でクラスを継承したいと思う人がいるかもしれません(おそらく数年後、誰かがその素晴らしいアイディアを考えると思います)。

また、私が気づいていないC++でこれを禁止したいと思っている理由がありますか?参考のため

これは私が各言語で行った実験をした

のJava

public class Base { 

    void doSomething(){ 
    System.out.println("Doing the base thing"); 
    } 
    } 
    public class Derived extends Base { 

    void doSomething(){ 
    System.out.println("Doing the derived thing"); 
    } 

    public static void main(String... argv){ 
     Base object = new Derived(); 
     object.doSomething(); 
    } 
    } 

C++

class Base 
    { 
    public: 
     Base(void); 
     ~Base(void); 
     virtual void doSomething(); 
    }; 

    void Base::doSomething(){ 
     std::cout << "I'm doing the base thing\n" << std::endl; 
    } 

    class Derived : 
     public Base 
    { 
    public: 
     Derived(void); 
     ~Derived(void); 
     void doSomething(); 
    }; 

    void Derived::doSomething(){ 
     std::cout << "I'm doing the dervied thing" << std::endl; 
    } 


    int main(void){ 

     Base * object = new Derived; 

     object->doSomething(); 
     return 0; 

    } 
+0

の可能重複[仮想ようにC++関数をマークします?](http://stackoverflow.com/questions/8298041/when-to-mark-a-function-in-c-as-a- virtual) –

答えて

1

ダフィモとアルはあなたを正しい方向に向ける。あなたは あなたのクラスから を継承あなたが誰かがいくつかの段階ですることがありますことを感じた場合にC++でそう

(多分年後に誰かがそのクールなアイディアを考えている)ん:私はちょうどあなたが言った一つのことにコメントしたかったですあなたのすべてのメソッドを仮想化しますか?

ソフトウェアエンジニアリングの観点からは、継承のための即時の使用がなく、インターフェイスを使用していない場合は、メソッドを仮想として宣言することはお勧めしません。

仮想メソッドは、これまでそうわずかパフォーマンスの低下が付属しています。重要ではないコード・パスでは、perf影響は無視できる程度です。しかし、多く呼び出されるクラスメソッドについては、それが足りるかもしれません。コンパイラは多くのインライン展開と直接リンクを行うことはできません。代わりに、呼び出される仮想メソッドは、実行時にvテーブル配列で参照される必要があります。

私のコーディングチームの誰かが持つデザインの会話から始まり、「誰かが後でいくつかの点でもできますが...」私の「未来の校正」アンチパターンのアラームがオフになったときだという。拡張性のための設計は一つのことですが、「未来のための機能」はそれまで延期されるべきです。

それに - それはクールなアイディアだと思っ後の男の年は - 彼は仮想であることをクラスメソッドを変換所有するいずれかになりましょう。とにかく大きなプロジェクトになるでしょう。 :)仮想関数がデフォルトな言語から来る

+0

仮想メソッドのパフォーマンスヒットは、Cのための唯一の真実であることを注意++または異なる上書きされた方法が実際に存在する場合(その場合でも、それは楽観インライン化することができ、など) – Voo

1

それならばはい、C++ではクラスメソッドのみoveriddenすることができベースクラスにvirtualとマークされています。

クラスが継承のために作成されていて、クラスメソッドがBaseとderivedに対して異なる動作を提供する場合は、メソッドをvirtualとマークします。

グッド読む:

When to mark a function in C++ as a virtual?

1

はい、あなたはすべてのあなたの方法は、仮想作る必要があるだろう。

Javaは、すべてがデフォルトでオーバーライドするための公正なゲームであり、それを禁止することはアクションを必要とするという立場を取った。 C++とC#は逆の見方をしています。

0

virtualがなくても、ベースクラスのメソッドをオーバーライドできます。

例えばこの小さなプログラムください:プログラムからの出力

#include <iostream> 

struct A 
{ 
    void m() 
     { std::cout << "A\n"; } 

    virtual void n() 
     { std::cout << "A\n"; } 
}; 

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

    virtual void n() 
     { std::cout << "B\n"; } 
}; 

int main() 
{ 
    A a; 
    a.m(); 
    a.n(); 

    B b; 
    b.m(); 
    b.n(); 

    A &c = b; 
    c.m(); 
    c.n(); 
} 

は次のとおりです。

 
A 
A 
B 
B 
A 
B 

あなたは、Aで同じメソッドをオーバーライドB::m方法を見ることができるように。しかし、これはBの正確なインスタンスを使用する場合にのみ機能します。 3番目のケースでは、基本クラスへの参照を使用する場合は、それを動作させるにはvirtualが必要です。

+4

'overidding'のために' virtual'キーワードが必要です。あるいは 'Function Hiding'が得られます。派生構造体 'B'のメソッド' m() 'は、基本構造体' A'メソッドを隠しますが、 'B 'の' n() 'メソッドは基本構造体メソッドをオーバーライドします。 –

+0

Bでm()を使ったことはオーバーロードと呼ばれ、オーバーライドされず、オーバーライドされません。 C++では、オーバーライド可能にするために関数を明示的に仮想宣言する必要があります。 –

0

プログラマがC++はデフォルトの逆の選択肢を持っていることに驚いになる傾向があり、すなわち非仮想がデフォルトです。すべてのオーバーライド機能の

  1. 契約、すなわち機能は概念的に何をするか:関与する2件の異なる契約が実際に存在するため、[コンクリート]仮想関数の契約は、ドキュメントやテストに多くの困難であること、しかし、注意してください
  2. 具体的な機能は、他の半分は全く明らかではないので、唯一のこれらのは、実際にそれをカットされません文書化

を行うには何が起こるかの契約。これはまた、特定の実装から実際の契約が何であるかを見ることができないことを意味します(ソースがドキュメントを提供するという非常に典型的でない状況にいると仮定して)。

+1

すべてが仮想作ったりしないことがあり、一般的に継承する理由の1例本当によく考えてみると、Javaの 'HashMap'から継承した人たちが、彼らが思っていたようなものになっていないことがよくあります。 – Voo

関連する問題