2012-04-03 6 views
16

次のC++コードは正しいと思いますが、「-Woverloaded-virtual」でコンパイルするといくつかの警告が表示されますが、警告が偽であるか、このコードに問題がありますか?それは私がそれを避けるために何ができるか偽の警告がある場合gcc Woverloaded-virtual warnings

は、警告の派生のgetのRIDにすべての例外の仮想バリアントを定義多分よりよい解決策がある

G ++コマンド:

g++ -c -Woverloaded-virtual test.cpp 
test.cpp:22:18: warning: ‘virtual void intermediate::exception(const char*)’ was hidden [-Woverloaded-virtual] 
test.cpp:32:18: warning: by ‘virtual void derived::exception()’ [-Woverloaded-virtual] 

C++コード

using namespace std; 

class base 
{ 
public: 

    virtual void exception() = 0; 
    virtual void exception(const char*) = 0; 
}; 

class intermediate : public base 
{ 
public: 

    virtual void exception() 
    { 
    cerr << "unknown exception" << endl; 
    } 

    virtual void exception(const char* msg) 
    { 
    cerr << "exception: " << msg << endl; 
    } 
}; 

class derived : public intermediate 
{ 
public: 

    virtual void exception() 
    { 
     intermediate::exception("derived:unknown exception"); 
    } 
}; 

答えて

18

警告があることを意味:あなたは、あなたのを動的ディスパッチを使用していない場合は
クラスオブジェクトは、

void exception()  

を呼び出すことができ、それが基本クラスintermediateのすべての同じ名前のメソッドを非表示になります。

派生クラスオブジェクトが基本クラスintermediateのすべての同じ名前付きメソッドを呼び出せるようにするには、derivedクラスに次の行を追加する必要があります。

using intermediate::exception; 

もちろん、これが問題であるかどうかを判断するのに最適な立場にあります。

+0

意図的な場合、この警告をどのように抑制しますか? – Sampath

+0

私は確信していませんが、私は 'void例外(const char * msg)= delete;'がうまくいくと思います。編集:いいえ、そのような過負荷を削除するエラーです。しかし、これが本当に意図的であれば、うまく設計されたコードで驚くでしょう。派生クラスのインスタンスを基本クラスのインスタンスのように扱うことができるはずです。 –

+0

他の答えに指摘されているように、あなたはそれを 'プライベート'と再定義することができます。 –

13

警告はあなたが親クラスがそれを定義し、それが仮想的であっても、(またはderivedへのポインタ経由)タイプderivedのオブジェクトにderived::exception(const char*)を呼び出すことができないという事実によるものである(そう、あなたはそれがあることを期待します利用可能なderived)。あなたは、他の人にそれを公開していないdefintionとプライベートとして宣言したくない場合は

class derived : public intermediate 
{ 
public: 
    virtual void exception(const char* msg) {intermediate::exception(msg);} 
    virtual void exception() 
    { 
    intermediate::exception("derived:unknown exception"); 
    } 
}; 

をまたは:警告を削除するには、derivedにそのメンバ関数を公開する必要があります。

class derived : public intermediate 
{ 
public: 
    virtual void exception() 
    { 
    intermediate::exception("derived:unknown exception"); 
    } 
private: 
    void exception(const char* tmp); 
}; 

UPDATE:usingディレクティブ(ALSによって指摘されているようにと)をダブルチェックした後、あなたもこれを行うことができます:クラスの

virtual void exception(const char* msg);

class derived : public intermediate 
{ 
public: 
    using intermediate::exception; // imports both declarations from intermediate 
    virtual void exception() // will not clash with the imported declaration of the 
          // same signature, but properly overriders the parent 
          // class's defition 
    { 
    intermediate::exception("derived:unknown exception"); 
    } 
}; 
+0

基本クラスの関数を派生クラスで公開するには、OPを使用するために 'intermediate :: except;'を追加する必要があります。 –

+0

私はそうは思わない(http:// ideone。com/deM6L) –

+0

実際には、私は私の元の投稿で使っていると思っていましたが、それに反対して決めました(私が最初からコメントしたのと同じ理由で、 )。あなたのコメント(そして本能による私の執筆)の後、私は二重チェックして確かめた。あなたが正しいと思った後、私はあなたの2番目のコメントをリンクに気づいた私の答え、aferを更新しました。もちろん、あなたはそれのために私のfordを取る必要があります...しかし、私は再び更新されますので、誰も苦労しません:) – Attila

0

機能を再定義してください。 "派生した"。

あなたのコードは警告なしでコンパイルされます。

+0

警告なしでコンパイルしますが、誰かが呼び出すとODRの問題が発生しました。これらはおそらくリンカーエラーとして現れます。リンカーエラーは、コンパイラーの警告やコンパイラーのエラーよりも読みやすく理解しにくいものです。 –