パラメータの前のconstと関数名の後のconstc ++


90

このようなものの違いは何ですか

friend Circle copy(const Circle &);

そしてこのようなもの

friend Circle copy(Circle&) const;

関数を使用して、この関数が呼び出されたオブジェクトを変更しようとしないことをコンパイラーに通知した後、constを知っていますが、他のオブジェクトはどうですか?


6
パラメータを変更しないのはもう1つです
Chad

回答:


199

最初の形式はCirclecopy()関数のパラメーターである参照にバインドされたオブジェクト(の状態)が、copy()その参照を介して変更されないことを意味します。参照はへの参照であるためconst、それCircle自体がとして修飾されていないその参照を介してのメンバー関数を呼び出すことはできませんconst

一方、2番目の形式は違法です。メンバー関数のみをconst修飾できます(宣言しているのはグローバルfriend関数です)。

constメンバー関数を修飾する場合、修飾は暗黙のthis引数を参照します。言い換えると、その関数は、呼び出されたオブジェクト(暗黙のthisポインターが指すオブジェクト)の状態を変更することはできません-mutableオブジェクトを除いて、それは別の話です。

コードでそれを言うには:

struct X
{
    void foo() const // <== The implicit "this" pointer is const-qualified!
    {
        _x = 42; // ERROR! The "this" pointer is implicitly const
        _y = 42; // OK (_y is mutable)
    }

    void bar(X& obj) const // <== The implicit "this" pointer is const-qualified!
    {
        obj._x = 42; // OK! obj is a reference to non-const
        _x = 42; // ERROR! The "this" pointer is implicitly const
    }

    void bar(X const& obj) // <== The implicit "this" pointer is NOT const-qualified!
    {
        obj._x = 42; // ERROR! obj is a reference to const
        obj._y = 42; // OK! obj is a reference to const, but _y is mutable
        _x = 42; // OK! The "this" pointer is implicitly non-const
    }

    int _x;
    mutable int _y;
};

12
ヘルルバの答え!ありがとうございました!
SexyBeast 2015年

1
したがって、2番目のケースでは、クラスのconstオブジェクトがobjありX、のbar()ように呼び出すとobj.bar(obj)、何が起こるはずで、なぜですか?呼び出し元で宣言されているobj._x = 42ので、失敗するべきではありませんか?objconst
SexyBeast 2015年

1
後者のバー関数(void bar(X const& obj) {...})をこのようにした場合はどうでしょうか?void bar(const X& obj) {...}constキーワードをこの場所に移動すると、何か変更がありますか?もしそうなら、この例も追加していただけますか?
ガブリエルステープルズ2017

1
@GabrielStaplesそれらは同じです。const左側にあるもの、または左側に何もない場合は右側にあるものに適用されます。あなたの場合、両方のバージョンconstがに適用されていることがわかりますX
アンドレアスFlöjt

70

C ++クラスのメソッドには、thisすべての明示的なパラメーターの前にある暗黙的なパラメーターがあります。したがって、次のようなクラス内で宣言された関数:

class C {
  void f(int x);

あなたは本当にこのように見えると想像することができます:

  void f(C* this, int x);

さて、あなたがそれをこのように宣言すると:

  void f(int x) const;

これを書いたかのようです:

  void f(const C* this, int x);

つまり、末尾constthisパラメータconstになります。つまり、クラスタイプのconstオブジェクトでメソッドを呼び出すことができ、メソッドは呼び出されたオブジェクトを変更できません(少なくとも通常のチャネル経由ではありません)。


2
完全に正しいですが、実際にはクラスメソッドではなく、フレンド関数を参照しているという質問には答えられません。
mah

5
ええ、私はそのfriend部分を無視することにしました。なぜなら、それは実際にはOPの実際の質問(またはすべての問題が明らかになったときに実際の質問がどうなるか)とは無関係だと思うからです。だからそれでいい。
John Zwinck 2013

constオブジェクトまたは非constオブジェクトでconstメソッドを呼び出すことができるのに対し、non-const関数は非constオブジェクトでのみ呼び出すことができるため、「クラスタイプのconstオブジェクトでメソッドを呼び出すことができる」と言うのは少し誤解を招くと思います。そう、これは私のお気に入りの答えである
csguy

8
Circle copy(Circle&) const;

関数const自体を作成します。これは、クラス/構造体のメンバー関数にのみ使用できます。

メンバー関数を作成するconstということは、

  • const以外のメンバー関数を呼び出すことはできません
  • メンバー変数を変更することはできません
  • それによって呼び出すことができますconst(対象constオブジェクトのみ呼び出すことができるconst機能を)。非constオブジェクトもconst関数を呼び出すことができます。
  • それはしなければならないクラスのメンバー関数でサークル"。

次のことを考えてみましょう。

Circle copy(const Circle &);

これは、渡されたパラメーターを関数内で変更できないことを意味します。クラスのメンバー関数である場合とそうでない場合があります。

注:const同じ関数の非constバージョンを持つような方法で関数をオーバーロードすることが可能です。


8

関連するすべての混乱を解消しましょう const


const一定の意味から来たのは、何かが変更可能ではなく、読み取り可能であることを意味します。

  1. 変数をconstキーワードで修飾すると、後で変更することはできません。
    たとえば、const変数は、宣言時に初期化する必要があります。
    constint var =25;
    var =50; // gives error

  2. ポインタ変数をafterで修飾するとポインタ自体を変更することできませんが、ポインタの内容は変更可能です。 例 //しかしconst *

    int *const ptr = new int;
    ptr = new int; //gives error

    *ptr=5445; //allowed

  3. 我々が私達のポインタ変数を修飾する場合は前に我々はできる、ポインタ自体を変更するが、ポインタの内容は変更できません。 例 //しかしconst *

    intconst* ptr = new int(85);
    //or
    constint * ptr = new int(85);
    ptr = new int; // allowed

    *ptr=5445; // gives error

  4. ポインタとコンテンツの両方定数
    など
    intconst*constptr = new int(85);
    //or
    constint *constptr = new int(85);
    ptr = new int; // not allowed
    *ptr=5445; // not allowed


  1. Circle copy(const Circle &);
    ここでconstCircleは、Circleの値が読み取り可能であることを意味します。関数内でCircleの値を変更しようとすると、エラーが発生します。
  2. friend Circle copy(Circle&) const;
    このタイプの関数は、非メンバー変数用ではありません。クラスまたは構造体に使用されます。ここで、関数全体がconstキーワードで修飾されているということは、オブジェクトメンバー変数を変更できないことを意味します。例えば
    class A{ public :
              int  var;
              void fun1()
                    { var = 50; // allowed
                    } 
              void fun2()const
                       { var=50; //not allowed
                       }
           }; 

4

1つはパラメーターを参照し、もう1つは関数を参照します。

Circle copy(const Circle &);

これは、渡されたパラメータを関数内で変更できないことを意味します

Circle copy(Circle&) const;

const修飾された関数は、メンバ関数やオブジェクトそのもののデータメンバーを変更することができないことを意味するために使用されています。あなたが投稿した例は無意味でした。

右から左に読む

最初の関数をCircle copy(Circle const&);、同じことを意味するように書き直すと、右から左に読むことが役立つことが明らかになります。オブジェクトcopyconst参照を取得し、参照によってCircleオブジェクトを返す関数ですCircle


0

friend Circle copy(const Circle &);//関数の定数パラメータを参照します。パラメータによって保存された値を変更することはできません。

例のCirclecopy(Circle&)const;で友達を削除する必要があります //定数メンバー関数として指定されたこのponiter値を変更することはできません


0
friend Circle copy(const Circle &);

パラメータの値は、関数呼び出し中に変更されません。

friend Circle copy(const Circle &)const ; 

この関数は、クラスメンバーの値を変更しないアクセサーです。一般に、関数にはアクセサとミューテータがあります。アクセサ:オブジェクトの状態を調べますが、変更しません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.