2012-01-11 7 views
10

私は仮想キーワードと継承の概念をC++でテストしています。 私は小さなプログラムを書かれている:私はここでやっていること子クラスの仮想関数のオーバーロード

#include<stdio.h> 
#include<iostream> 

using namespace std; 

class cna_MO 
{ 
    public: 
    virtual void print() 
    { 
     cout << "cna_MO" << endl; 
    } 
}; 

class cna_bsc:public cna_MO 
{ 
    public: 
    void print() 
    { 
     cna_MO::print(); 
    } 

    void print(int a) 
    { 
     cout << "cna_BSC" << endl; 
    } 
}; 

class cna_Mo 
{ 
    cna_MO *_mo; 

    public: 
    cna_Mo() 
    { 
     _mo = new cna_bsc; 
    } 

    virtual void print(int a) 
    { 
     cout << "cna_Mo with arg" << endl; 
     _mo->print(5); 
    } 

    virtual void print() 
    { 
     cout << "cna_Mo" << endl; 
     _mo->print(); 
    } 
}; 

int main() 
{ 
    cna_Mo valid_mo; 
    cout << "old case is started" << endl; 
    valid_mo.print(); 
    cout << "new case is started" << endl; 
    valid_mo.print(5); 
    return 0; 
} 

は、私は子クラスに親クラスの仮想関数をオーバーロードしています!これは正しいことではありませんか?

私は以下のようにコンパイルエラーを取得しています:

"temp10.cc", line 45: Error: Too many arguments in call to "cna_MO::print()".

+1

本当に 'stdio'が必要な場合(あなたが指定したコードでは必要ありません)、' 'stdio.h'ではなく' cstdio'をインクルードする必要があります(http://stackoverflow.com)。/questions/301586/what-is-the-the-difference-using-includeファイル名とファイル名-h)。 –

+0

また、cna_Moコンストラクタで割り当てるポインタを決して削除しないでください。 –

答えて

23

あなたが派生クラスで基本クラスから関数をオーバーロードすると基本クラスで同じ名前を持つすべての関数が派生クラスの中に隠します。

関数cna_bsc::print(int a)を派生クラスに追加すると、関数cna_MO::::print()は派生クラスのユーザーに表示されなくなりました。これは関数隠蔽と呼ばれます。

ソリューション: 派生クラスで隠された機能が見えるようにするために、あなたは追加する必要があります。

using cna_MO::print; 

あなたの派生クラスcna_bscpublicセクションで。

グッド読む:

What's the meaning of, Warning: Derived::f(char) hides Base::f(double)?

+0

私はあなたの意見を持っていますが、まだ私はもう一つ問題があります...質問を編集してください。私はあまりにも多くのagrsエラーが発生している変更を行った後now.evenを確認してください。 – Vijay

+3

'_mo-> print(5);を呼び出すとエラーが' cna_MO :: print() 'にあります' '_mo'は' cna_MO * '型で' cna_MO'クラスは 'print() '関数は単一の引数をとり、したがってエラーをとります。 ** –

0

子クラスでの印刷機能はパラメータを受け取り、オリジナルにはないからです。 cna_MO(親クラス)で

:cna_bsc(子クラス)で

virtual void print() 

void print(int a) 

基本的に子供の印刷は、int型の引数を取るべきではありません。

void print() 

編集:

おそらく、intをオプションで渡すのが最善でしょうか?

例:cna_MO(親クラス)で

virtual void print(int a=-1) { 
    if (a == -1) { 
     // Do something for default param 
    } else { 
     cout << a; 
    } 
} 

cna_bsc(子クラス)内:

void print(int a=-1) 

そう== -1の場合、あなたはおそらく、想定することができます彼らは何も渡さなかった。

トリッキーは、親と子の両方が同じ戻り値の型と同じ引数型を意味する同じメソッドを必要とすることです。

+0

編集した質問 – Vijay

+0

を参照してください。これは、あなたがその行のintを渡して呼び出しているからです: 'あなたの混乱の理由は、 valid_mo.print(5); ' – matiu

0

基本クラスと同じ名前と異なるパラメータを派生クラスに持つと、その関数はになり、になります。あなたはcna_MO *与え、あなたは先の尖っがないことをコンパイル時に見ることができるので、動作しないことができるようなBase::hiddenFun();

+0

編集した質問をご覧ください – Vijay

0

を呼び出すことにより、特定の隠された関数を呼び出すことができます。..

を詳細hereを見つけることができます(必然的に)intの過負荷を持っています。実際にベースクラスのオブジェクトを指している場合は、_mo->print(5);は実際に何も呼び出す必要がありません。また、この呼び出しをサポートする必要のない(まだ実装されていない)派生クラスが無限に存在することがあります。

  1. すべての派生クラスはprint(int)を持っている必要があります - 基底クラスでそれを宣言する。 cna_Moのみcna_bscで動作しますので、メンバーはcna_bsc* _moをする必要があります -

  2. すべての派生クラスはprint(int)を持つ必要はありません。

0

理想的にはint型をとり、あなたの印刷は、別の名前を持っている必要がありますが、あなたは、両方の機能が、印刷と呼ばれるようにしたい与え、あなたは彼らが両方の非仮想作り、それらが保護された仮想関数を呼び出す行う必要があります。

class cna_MO 
{ 
    public:  
    void print() { doPrint(); } 

    protected: 
    virtual void doPrint() 
     {   cout << "cna_MO" << endl;  
     } 
}; 


class cna_bsc:public cna_MO 
{ 
    protected:  
     virtual void doPrint() 
        // although with implementation no need to override it 
     {   
      cna_MO::print();  
     } 

    public: 
    void print(int a)  
     { 
      doPrintInt(a); 
     } 

    protected: 
     virtual void doPrintInt(int) 
     { 
     cout << "cna_BSC" << endl;  
     } 
}; 
0

あなたが本当にすなわち、一つのクラスへのポインタを持っており、派生クラスとして初期化し、このようにそれを行う必要がある場合は、それを使用しているときは常に正しい型へのポインタをキャストするしか選択の余地はありません。この場合、((cna_bsc*)_mo)->print(5);

関連する問題