2017-01-02 15 views
1

次のコードは正常にコンパイルされます。オーバーロード時のC++コンパイルエラー

#include <iostream> 
#include <vector> 
using namespace std; 

class MyClass 
{ 
public: 
    MyClass() 
    { 
     x.resize(2); 
     x[0] = 10; 
     x[1] = 100; 
    } 
    std::vector<int> getValue() 
    { 
     return x; 
    } 
    const std::vector<int>& getValue() const 
    { 
     return x; 
    } 
private: 
     std::vector<int> x; 
}; 


int main() 
{ 

    MyClass m; 
    std::vector<int> y = m.getValue(); 
    for(int i=0; i<y.size(); i++) 
    { 
     std::cout<<y[i]<<std::endl; 
    } 

    const std::vector<int>& z = m.getValue(); 
    for(int i=0; i<z.size(); i++) 
    { 
     std::cout<<z[i]<<std::endl; 
    } 
    return 0; 
} 

しかし、(「CONST」(スタンダード::ベクトルのgetValueを添加することにより(関数はオブジェクトを変更することになっているので)私がより正しいバージョンへの「スタンダード::ベクトルのgetValue()」を変更したとき)const)次のコンパイルエラーが発生します。

error: 'const std::vector<int>& MyClass::getValue() const' cannot be overloaded const std::vector<int>& getValue() const 

なぜですか?

私はあなたが戻り値の型が異なるだけで、同じ名前を持つ2つの関数を定義することはできません「gccのバージョン4.8.4(〜14.04.3 Ubuntuの4.8.4-2ubuntu1)」

+0

私はよく分からないが、おそらく&リターンで(アドレス演算子)を通過します。Constのstd ::ベクトル&のgetValue()constは { リターンを&バツ; } –

+2

コンパイルされていないバージョンを投稿してください。 –

+1

@RSahu最初のコードは正しいです。ポストの後半に記載されている変更により、コード –

答えて

5

を使用していました。したがって、たとえば、異なる名前の関数を定義します。

std::vector<int> getValueCopy() const; 
3

あなたはgetValue曖昧への呼び出しをレンダリングする最初の関数にconstを追加することにより:これらの2つの機能の違いは何ですか:

std::vector<int> getValue() const;  // 1 
const std::vector<int>& getValue() const; // 2 

まあ、彼らが戻り値を除いて同じですが、待機してください! C++の戻り値の型に基づいてオーバーロードすることはできません!

std::vector<int> y = m.getValue(); // which one? It can be 1, it can be 2 (std::vector<int> 
            // is not a better match than const std::vector<int>&) 

const std::vector<int>& z = m.getValue(); // same as above 

m.getValue(); // which one? 

でも、2つの違いは何でしょうか?

最初のものは100%安全ですが、2番目のものは安全ではありません。xへの参照を格納することができ、オブジェクトが破棄されるとダングリングリファレンスになります。そして、もし可能であれば、あなたは2番目のものを取り除くと言います。

+0

私は、C++ではあいまいさを避けるために戻り値の型が異なる関数のオーバーロードを許可していないことを理解しています。しかし、この例では、本当にあいまいさが存在しますか? const std :: vector &z = m.getValue()は明らかにアドレスを返す必要がありますが、最初のものはコピーを返す必要があります。 – Soo

+0

@Sooはい、実際にはあいまいさがあります:rvalue(最初の 'getValue')*または*を別の参照(2番目の' getValue')で 'const&'を初期化できます。どちらも可能ですが、コンパイラはどちらを呼び出したいのか分かりません(たとえそれが自明であっても)。 'std :: vector &v = m.getValue()'と書くと、曖昧さはなく、rvalueで参照を初期化できないので、2番目のオーバーロードが選択されることに注意してください。 – Rakete1111

1

あなたの問題は、関数の定義は、引数の型や引数リスト内の引数の数によって互いに異なる必要があります機能をオーバーロードするときに、コンセプト

をオーバーロード機能を理解していなかったということです。

戻り値の型によってのみ異なる関数宣言をオーバーロードすることはできません。あなたの関数で

:それはオーバーロード関数とはみなされないことになるので、

std::vector<int> getValue() const 

const std::vector<int>& getValue() const 

それだけで、あなたのエラーを修正する

最良の方法は、getValuev2()

に2番目の関数名を変更することです戻り値の型が異なります

またはいずれかの関数の引数を変更します。

あなたがC++でオーバーロードの詳細を読むことができます: https://www.tutorialspoint.com/cplusplus/cpp_overloading.htm

+1

実際に投稿した機能は有効なオーバーロードです。末尾の 'const'はすべての違いを作ります。 – juanchopanza

+0

@juanchopanzaはオーバーロードコンセプトでは戻り値の型だけが異なるため、有効ではありませんが、なぜ後続の 'const'によってすべての違いが生じますか? – Oghli

+1

はい、2つの関数*は戻り値の型だけが異なります*。 – juanchopanza

関連する問題