1883


C++ではconstキーワードを利用して以下のように定義することができると思います:

[code]

    class A{
        const void B(const A const & const z) const;
    };
    
[/code]

この定義を分解すると、以下のパターンに分解できると思います。

[code]

        const void C(A & z);
        void D(const A & z);
        void E(A const & z);
        void F(A & z) const;
        void G(A & const z);
    
[/code]

これらの定義の仕方についての違いがわかりません。もし違いがあるとするならば、その違いについて教えて下さい。


CC BY-SA 3.0
2014-12-17T04:41:57.837
1861
2014-12-17T07:30:14.737
2014-12-17T05:54:19.867
question
c++
C++クラスでのconstの定義方法について

[code]

    const void C(A & z);
    
[/code]

は返り値に対する `const`です。 この場合には返り値が `void` なので意味はありませんね。

[code]

    void D(const A & z);
    void E(A const & z);
    
[/code]

はどちらも同じ意味で `z` に対する `const` です。

[code]

    void F(A & z) const;
    
[/code]

は `static` でないメンバ関数として宣言しなければコンパイルエラーとなったと思います。 これは `*this` に対する `const` です。
この関数内ではオブジェクトのメンバ変数を変えようとするとコンパイルエラーになるはずです。

色々と自分の手で試してみたください。


CC BY-SA 3.0
2014-12-17T05:11:46.600
1867
2014-12-17T05:33:11.323
2014-12-17T05:33:11.323
208
4440
1861
answer

[code]

    class A{
        const void B(const A const & const z) const;
    //  ~~~~         ~~~~~   ~~~~~   ~~~~~    ~~~~~
    //  (1)          (2)     (3)     (4)      (5)
    };
    
[/code]

メンバ関数で`const`キーワードを書いた位置と、それぞれの意味は下記の通りです：

  * (1) 戻り値型に対するconst修飾となります。このメンバ関数の戻り値型は`const void`です。（この例だと実用上の意味はありませんが）
  * (2) メンバ関数宣言において、型`A`に対するconst修飾となります。このメンバ関数の1個目の引数型は`const A &`（`const A`への参照型）です。
  * (3) (2)と完全に同じ意味です。ただし(2)と(3)の2箇所同時に`const`を置くとコンパイルエラーになり、どちらか一方にしか指定できません。
  * (4) メンバ関数定義において、関数パラメータ変数`z`に対するconst修飾となります。この例では "参照型に対するconst修飾" となるため、コンパイルエラーです。例えばポインタ型`const A * const z`であれば、変数`z`の型は "`const A`型へのconstポインタ" のように使えます。
  * (5) `this`オブジェクトに対するconst修飾、いわゆる「constメンバ関数」となります。このメンバ関数内での`this`の型は`const A *`です。


CC BY-SA 3.0
2014-12-17T06:49:21.650
1883
2014-12-17T06:49:21.650
49
1861
answer


質問が不明確な部分があるので次のように解釈します。

## 質問

次のようなクラスAを考える。

[code]

    class A {
        A() : a(), b() {}
    
        const void C( A & z);
        void D(const A & z);
        void E(A const & z);
        void F(A & z) const;
        //void G(A & const z);
    
        int a;
        const int b;
    };
    
[/code]

クラスAのメンバ関数C,D,E,F(,G)の違いを述べよ。

## 回答

  * const void C(A& z)  
返り値の型：const void  
呼出し可能：zのC,D,E,FとthisのC,D,E,F  
読出し可能：zのa,bとthisのa,b  
書込み可能：zのaとthisのa  
備考：const voidはconst修飾されていないvoidと区別されます（これはvoidだけでなく他の型でも同様です）。  
しかしvoid型変数は存在できないので型演算の時以外でこれが問題になることは無いでしょう。

  * void D(const A& z)

  * void E(A const& z)  
返り値の型：void  
呼出し可能：zのFとthisのC,D,E,F  
読出し可能：zのa,bとthisのa,b  
書込み可能：thisのa  
備考：const修飾子の位置が違うだけでDとEは（名前を除き）宣言の形は同じです。

  * void F(A& z) const  
返り値の型：void  
呼出し可能：zのC,D,E,FとthisのF  
読出し可能：zのa,bとthisのa,b  
書込み可能：zのa

  * void G(A& const z)  
const修飾子を参照型の後に書くことはできません。  
（ただし、ポインタ型では可能で、意味が異なります。"const T* t"もしくは"T const*
t"はポインタtの指しているオブジェクトがconst修飾されます。"T* const t"はポインタtがconst修飾されます。）

まとめると今回の質問で考慮しなければいけないことは、以下の事柄だと思います。

  * クラスAのメンバ関数は引数にとったクラスA型のオブジェクトのメンバにたとえ非公開であってもアクセスできる。（ちなみに今回のクラスAのメンバC,D,E,F,a,bは全て非公開になっている）
  * ただし、基本的にconst修飾されたオブジェクト（今回はD,Eの仮引数zとb）に変更を加えることはできない。
  * また、基本的にconstメンバ関数（今回はF）はメンバ変数（今回はa（,b））に変更を加えることはできない。（constメンバ関数は非constメンバ関数を基本的には呼び出せない）
  * "const T&"と"T const&"に違いはない。"T& const"はできない。
  * "const T MemberFunc()"と"T MemberFunc() const"は根本的に意味が異なる。前者は返り値型がconst修飾され、後者はconstメンバ関数となる。


CC BY-SA 3.0
2014-12-17T07:30:14.737
1889
2014-12-17T07:30:14.737
4548
1861
answer