2017-07-27 28 views
8

私はC++を学び、仮想キーワードについて学んでいます。私はそれを無駄に理解しようとインターネットを精査した。私はエディタに入り、次の実験を行いました。基本メッセージを2回印刷することを期待していました。なぜなら、仮想キーワードが機能を無効にする必要があるからです。しかし、それは2つの異なるメッセージを印刷しました。関数を単純にオーバーライドしても一見多態的な振る舞いをすることができるのであれば、なぜ仮想キーワードが必要なのか誰かが私に説明することはできますか?おそらく誰かが私と将来の他の人々がバーチャルとオーバーライドを理解するのを助けることができます。 (私が得ている出力は "私はベースです"、 "私は派生している"です)。あなたがタイプDerivedので、コンパイラは、関数が使用することを知っているであるとbを宣言したのでC++仮想キーワードと関数のオーバーライド

#include <iostream> 

using namespace std; 
class Base{ 
public: 
    void printMe(){ 
     cout << "I am the base" << endl; 
    } 
}; 
class Derived: public Base{ 
public: 
    void printMe(){ 
     cout << "I am the derived" << endl; 
    } 
}; 
int main() { 
    Base a; 
    Derived b; 
    a.printMe(); 
    b.printMe(); 
    return 0; 
} 
+2

注: 'using namespace std;'は習慣に慣れていないので、今すぐ止めることができます。 'std ::'接頭辞は理由のためにそこにあります:それはあなた自身のクラス、構造体および変数との衝突を避けます。 – tadman

+3

'Base * p = new Derived;を試してください。 p> printMe(); 'と' virtual'の有無を指定します。 – HolyBlackCat

+7

明確にするために、多態的な振る舞いは、ポインタまたはその基本クラスへの参照を通じてオブジェクトにアクセスするときに達成されます。 – DeiDei

答えて

11

次の例を考えてください。 virtualoverrideの必要性を示す重要な線は、c->printMe();です。 cのタイプはBase*であることに注意してください。ただし、多形性のため、派生クラスからオーバーライドされたメソッドを正しく呼び出すことができます。

#include <iostream> 

class Base{ 
public: 
    virtual void printMe(){ 
     std::cout << "I am the base" << std::endl; 
    } 
}; 

class Derived: public Base{ 
public: 
    void printMe() override { 
     std::cout << "I am the derived" << std::endl; 
    } 
}; 

int main() { 
    Base a; 
    Derived b; 
    a.printMe(); 
    b.printMe(); 
    Base* c = &b; 
    c->printMe(); 
    return 0; 
} 

出力

I am the base 
I am the derived 
I am the derived 
+3

あなたは 'override'キーワードの目的が何であるか説明していません。 –

+0

私は(私だけ)しましたが、人々は彼らが最初に見た答えに投票する傾向があります。 –

2

現在地の行動を見ていません。 virtualあなたは物事をミックスする必要がある必要がある理由を露出させるために:

int main() { 
    Base a; 
    Base *b = new Derived(); 

    a.printMe(); 
    b->printMe(); 

    delete b; 

    return 0; 
} 

bは、仮想関数テーブルにBaseプラスどんなのに機能を使用するために起こっていることを意味するタイプBase*です。これにより実装が中断されます。あなたは正しくvirtualというものを宣言して修正することができます。あなたが持っているコードで

+0

3行目の新しいキーワードの使い方について説明できますか?私はこの文脈で新作がどのようにして錆びついているのか少し錆びています私は型ベースのポインタを作成していることを知っています。派生クラスを保持するのに十分なメモリを割り当てていますか? 3行目はどのように機能しますか? –

+0

これは 'new'を使った単純なC++割り当てです。これはCの 'malloc'によく似ていますが、よりインテリジェンスが組み込まれていて、自動的にイニシャライザを呼び出します。よいC++リファレンスブックは 'new'と' delete'の基本をカバーするべきです。あなたが持っていなければ、[C++の作者によるもの](http://www.stroustrup.com/4th.html)は始めるのに適しています。 – tadman

+1

@tadman:私が他の答えにコメントしたように、最近のC++では一般的に悪い習慣とみなされているので、初心者向けのサンプルコードでは、裸の 'new'と' delete'を使用しない方が良いと思います。参照(または 'b =&a')はポイントを同様にします。 –

6

、あなたが行う場合は、この

Derived derived; 
Base* base_ptr = &derived; 
base_ptr->printMe(); 

あなたは何が起こると思いますか?メソッドが仮想ではなく、呼び出し元のオブジェクトの静的型(つまり、Base)からディスパッチが行われるため、I am the derivedが出力されません。それをvirtualに変更すると、呼び出されるメソッドはオブジェクトの動的型に依存し、静的型には依存しません。

2

overrideでは、C++ 11に追加された新しいキーワードです。

あなたはそれを使用する必要があるため:基底クラスが一致virtualメソッドが含まれている場合

  • コンパイラがチェックします。これはメソッド名や引数リストのタイプミス(過負荷が許されている)が、実際にはなかったときに何かが上書きされたという印象を引き起こす可能性があるため、重要です。

  • overrideを1つのメソッドに使用すると、overrideキーワードを使用せずに別のメソッドがオーバーライドされると、コンパイラはエラーを報告します。これは、シンボルの衝突が発生したときに不要なオーバーライドを検出するのに役立ちます。

  • virtualは、「上書き」を意味しません。クラスdoentでは、メソッドをオーバーライドするよりも "override"キーワードを使用して、単純に "virtual"キーワードを省略してこのメ​​ソッドを書くことができます。オーバーライドは暗黙的に行われます。開発者は、オーバーライドの意思を示すために、C++ 11の前にvirtualと書いていました。単純にvirtualとすると、このメソッドはサブクラスでオーバーライドできます。

+0

"virtualは" override "を意味するものではありません。省略した場合でも上書きは機能します。"私はあなたが派生クラスでそれを省略する場合は、あなたがベースで省略する場合ではないことを意味すると仮定します – ROX

+0

はいこれは私が意味するものです。私はテキストをより明確に改善しました。 –

関連する問題