48507


`//ここです//////`と書かれたコメント部のコードなのですが、エラーメッセージで

[code]

    [   'return': 'const Array<int> *const ' から 'Array<int> *' に変換できません。]
    
[/code]

と表示され何が違うのかがわかりません。また`int
main()`関数のほうでは例外処理のコードを書きました。returnの処理の場所で何かしないといけないのはわかるのですがどうすればいいのでしょうか？自分でわかる範囲で編集しましたがわかりません教えてもらえますでしょうか？  
const問題と思われます。

### int main() 関数部

[code]

    catch (Array<int>::IdxRngErr& x) {
        Array<int>::IdxRngErr y(x);
        Array<int> const *ptr = x.Ident();
        cout << "要素数範囲エラー" << y.Index() << '\n';
    }
    
[/code]

### Array.h部

[code]

    #pragma once
    // 配列クラステンプレートArray
    #ifndef ___ClassTemplate_Array
    #define ___ClassTemplate_Array
    
    //===== 配列クラステンプレート =====//
    template <class Type> class Array {
        int nelem;      // 配列の要素数
        Type* vec;      // 先頭要素へのポインタ
    
        //--- 添字の妥当性を判定 ---//
        bool is_valid_index(int idx) { return idx >= 0 && idx < nelem; }
    
    public:
    
        //----- 添字範囲エラー -----//
        class IdxRngErr {
            const Array<Type> *ident;
            int idx;
        public:
            IdxRngErr(const Array* p, int i) : ident(p), idx(i) { }//コンストラクタ
            int Index() const { return idx; }//要素数を返す関数
    
            //ここです。↓/////////////////////////////////////////
            Array<Type>* Ident()const { return ident; }//indentを返す関数
    
        };
    
        //--- 明示的コンストラクタ ---//
        explicit Array(int size, const Type& v = Type()) : nelem(size) {
            vec = new Type[nelem];
            for (int i = 0; i < nelem; i++)
                vec[i] = v;
        }
    
        //--- コピーコンストラクタ ---//
        Array(const Array<Type>& x) {
            if (&x == this) {                       // 初期化子が自分自身であれば…
                nelem = 0;
                vec = NULL;
            }
            else {
                nelem = x.nelem;                    // 要素数をxと同じにする
                vec = new Type[nelem];              // 配列本体を確保
                for (int i = 0; i < nelem; i++)     // 全要素をコピー
                    vec[i] = x.vec[i];
            }
        }
    
        //--- デストラクタ ---//
        ~Array() { delete[] vec; }
    
        //--- 要素数を返す ---//
        int size() const { return nelem; }
    
        //--- 代入演算子= ---//
        Array& operator=(const Array<Type>& x) {
            std::cout << "代入演算子\n";
            if (&x != this) {                   // 代入元が自分自身でなければ…
                if (nelem != x.nelem) {         // 代入前後の要素数が異なれば…
                    delete[] vec;               // もともと確保していた領域を解放
                    nelem = x.nelem;            // 新しい要素数
                    vec = new Type[nelem];      // 新たに領域を確保
                }
                for (int i = 0; i < nelem; i++) // 全要素をコピー
                    vec[i] = x.vec[i];
            }
            return *this;
        }
    
        //--- 添字演算子[] ---//
        Type& operator[](int i) {
            if (!is_valid_index(i))
                throw IdxRngErr(this, i);               // 添字範囲エラー送出
            return vec[i];
        }
    
        //--- const版添字演算子[] ---//
        const Type& operator[](int i) const {
            if (!is_valid_index(i))
                throw IdxRngErr(this, i);               // 添字範囲エラー送出
            return vec[i];
        }
    
    };
    
    #endif
    
[/code]


CC BY-SA 4.0
2018-09-18T09:44:09.647
48506
2018-09-18T10:18:25.773
2018-09-18T09:51:35.290
19110
question
c++
c++,return文でエラーの解決方がわからない。

[code]

    class IdxRngErr {
        const Array<Type> *ident;
        int idx;
    public:
        IdxRngErr(const Array* p, int i) : ident(p), idx(i) { }//コンストラクタ
        int Index() const { return idx; }//要素数を返す関数
    
        //ここです。↓/////////////////////////////////////////
        Array<Type>* Ident()const { return ident; }//indentを返す関数
    
    };
    
[/code]

`class IdxRngErr` のメンバー変数`ident`の定義は

`const Array<Type> *ident;`

となっており、`const`修飾子により、ポインタ`ident`の指している先の`Array`の内容は変更できないようになっています。一方、`ident`を返す関数の定義は

`Array<Type>* Ident()const { return ident; }`

であり、戻り値には`const`が付いていないので、呼び出し側では`Array`の内容を変更できてしまいます。これはメンバー変数の定義と矛盾するのでエラーになっています。

`Ident()
const`と、メンバー関数定義自体に`const`が付いているので紛らわしいですが、この`const`はクラス`IdxRngErr`の中身が関数呼び出しによっては変更されない、つまり`ident`の持っているアドレスと`idx`の値が変更されないという意味です。`ident`のアドレスが指している先の中身には`const`の効力は及びません。

* * *

エラーの直し方についてですが、クラスの設計意図によります。今回の場合、`IdxRngErr`クラスは例外通知に使われるクラスなので、それを使ってデータのアップデートを行うことはないだろうと思われるので、

`const Array<Type>* Ident()const { return ident; }//indentを返す関数`

と戻り値に`const`を付ければよいと思います。


CC BY-SA 4.0
2018-09-18T10:18:25.773
48507
2018-09-18T10:18:25.773
3605
48506
answer