2015-10-21 13 views

答えて

13

2つの機能は実際には同じではありません。 2番目の関数だけがメンバー関数constとして宣言されています。メンバーが呼び出されたオブジェクトがconstの場合、後者のオプションが使用されます。オブジェクトがconstでない場合、最初のオプションが使用されます。

例:

void any_func(const Type *t) 
{ 
    something = t->value(); //second `const` version used 
} 

void any_func2(Type *t) 
{ 
    something = t->value(); //first non-`const` version used 
} 

const宣言された両方の機能をconstまたは両方の非宣言された場合、コンパイラは、は(べき、とにかく)文句であろう。

7

異なる機能の署名のためconstカウントするので、なぜコンパイラはおよそ

を文句はありません。あなたの仮定は、ファンクションシグネチャが同じですが間違っています。
constとマークされた機能は、constインスタンスまたは参照のいずれかがType<T>の場合に呼び出されます。

どのように呼び出されているかを知るには?

機能でcout文を入れて、以下の例をテスト:

template <class T> 
class Type { 
    public: 
     Type() {} 
     T& operator=(const T& rhs) {value() = rhs; return value();} 
     T& value() { 
      std::cout << "non const version" << std endl; 
      return m_value; 
     } 
     T value() const { 
      std::cout << "const version" << std endl; 
      return m_value; 
     } 
    private: 
     T m_value; 
}; 

int main() { 
    Type<int> t; 
    t.value(); 

    Type<int> rt = t; 
    rt.value(); 

    Type<int>* pt = &t; 
    pt->value(); 

    const Type<int> ct; 
    ct.value(); 

    const Type<int>& crt = t; 
    crt.value(); 

    const Type<int>* pct = &t; 
    pct->value(); 
} 

あなたの代入演算子は、非constのバージョンを呼び出します。


あなたは常にRVO(戻り値の最適化)に頼ることはできない、と余分なコピーは(特に古いコンパイラの実装のために)取られる可能性があるため、constのバージョンは、より良い

const T& value() const { 
    std::cout << "const version" << std endl; 
    return m_value; 
} 

のようになります。


も代入演算子は、現在のインスタンスへの参照を返す必要があり注意:機能解像度優先に単語の

Type& operator=(const T& rhs) {value() = rhs; return *this;} 
5

カップル。コンパイラは、const/non const関数を次のように区別します。

クラスに与えられた名前と引数リストを持つconst関数のみがあれば、それは定数オブジェクトと非定数オブジェクトの両方で呼び出されます。この関数を呼び出した後、オブジェクトは(constでなくても)constを仮定します。つまり、その関数は他のconst関数だけを呼び出すことができます。

クラスに非const関数のみがある場合、非constオブジェクトに対して呼び出されます。 constオブジェクトに対してこの関数を呼び出そうとすると、コンパイルエラーが発生します。

クラスに両方の関数を使用できる場合、constバージョンはconstオブジェクトに使用され、非constバージョンは非constオブジェクトに使用されます。

説明の初期ミックスアップに私の注意を向けるために@owacoderに感謝します。

+3

私は第2段落のロジックが後方にあると思います。非 'コンス'関数**は 'const'オブジェクトに対して**呼び出すことはできません。 – owacoder

+0

@owacoderもちろん、可能です。自分自身を試してください。 – SergeyA

+0

@owacoder、私の悪い。あなたは正しいです、私はあなたのコメントを誤解し、私の答えを間違って入力しました。それを編集します。 – SergeyA

関連する問題