5

私は初心者のプログラマーであり、C++OOPでかなりの問題を抱えています。具体的には、今夜、配列に格納されている各画像へのポインタを使用して、イベントを取り込み、複数の画像を切り替える簡単なクラスを作成しようとしていました。配列自体へのポインタを返す「getter」関数を作成しようとすると、紛らわしい問題が発生しました。

基本的に、私は次のようなことをしようとしていました:

class SlideShow
{
public:
    image *getSlideArray();
private:
    image *slideArray[10];
};

そこで、各画像へのポインタを格納する配列が必要でした。また、配列自体のアドレスを返す関数も必要でした。getSlideArray()関数を定義しようとしたときに問題が発生しました...なぜそれが機能しなかったのか完全にはわかりません...

クラスのソースファイルで最初に試したことは次のとおりです。

image *SlideShow::getSlideArray()
{
    return this->slideArray;
}

この試みでは、コンパイラーは「this」キーワードの使用に関して問題を提起し続け、私が返そうとしたものは以前に指定されたタイプではないと言っていました。しかし、これは私がこれまでゲッター関数を書いてきた方法であり、単純な変数を使用するときに一般的に機能します...私の疑いは、「これ」がポインターであるという事実のためにここに問題があることです、および'slideArray'は、ポインターも含む配列へのポインターです...しかし、私はひどいので、そのレベルの参照は今のところ頭を超えています。ポインターの基本的な理解、アドレスと演算子を使用した参照などを収集するのにしばらく時間がかかりました。ポインターへのポインターとポインターの配列はさらに混乱します。

また、コードをコンパイルする1つの回避策を見つけたことにも言及する必要があります。(実行時に動作するかどうかを確認するために実際に実行することはできませんが。)私の回避策は、定義/ returnステートメントをクラス宣言自体(ヘッダーファイル内)に追加することでした。

class SlideShow
{
public:
    image *getSlideArray() {return *slideArray;);
private:
    image *slideArray[10];
};

今。これは正しくコンパイルされました...しかし、それは私にも混乱を招きます。一般に、配列(たとえば、intの配列)を返すときは、配列の0番目のスロットのアドレスを返すことを知っています。しかし、intArray [5]を返そうとした場合、それを返すときは、単に「intArray」と記述しますよね?基本的に、この状況で「slideArray」の前に*を追加する必要がある理由については混乱していません...

ですから、私がどちらの方法でそれをやろうとしても、それは私を混乱させます。ここにいくつかの「トリック」があり、それはおそらくポインターをポインターに戻すことと関係があることを私は知っていますが、私はそれを自分で解決することができませんでした。プログラミング、特にOOPを理解し始めることができるように、私は本当にこの主題を学びたいと思っています...

誰かが私がこれをよりよく理解するのを手伝ってくれる?

4

5 に答える 5

9

使用しているメソッド定義:

image *SlideShow::getSlideArray() {
    return this->slideArray;
}

へのポインタimageが返されていることを示します。ただし、の配列を返そうとしていますimage。次のいずれかを行う必要があります。

image *SlideShow::getSlideArray(int image_idx) {
    return this->slideArray[image_idx];
}

また

image **SlideShow::getSlideArray() {
    return this->slideArray;
}

すべての画像をまとめて返すか (2 番目のオプション)、1 つずつ返すか (最初のオプション) によって異なります。

ところで、まったく使用する必要はありませんthis。次のコードは、上記の 2 番目のオプションと同等です。

image **SlideShow::getSlideArray() {
    return slideArray;
}

前の説明で問題が解決するはずです。ただし、「生のポインター」と C スタイルの配列を使用する代わりに、STL コンテナーを使用することをお勧めします (それについては @juanchopanza の回答を参照してください)。

于 2012-08-23T08:23:41.263 に答える
4

ポインターまたはスマート ポインターの標準ライブラリ コンテナーを使用して、それを返します (ユースケースに応じて、値または参照によって)。

動的サイズの場合:

#include <vector>

class SlideShow
{
public:
    std::vector<image*> getSlideArray() const {return slideArray; }
private:
    std::vector<image*> slideArray;
};

静的サイズの場合 (C++11 のサポートを想定):

#include <array>

class SlideShow
{
public:
    std::array<image*, SOME_SIZE> getSlideArray() const {return slideArray; }
private:
    std::array<image*, SOME_SIZE> slideArray;
};

C++11 をお持ちでない場合は、std::tr1::arrayfrom header<tr1/arrayまたはを使用してみてくださいboost::array

于 2012-08-23T08:23:55.083 に答える
3

関数に不正な戻り型を指定したため、最初のアプローチは失敗します。次を使用する必要がありますimage**

image **SlideShow::getSlideArray()
{
    return this->slideArray;
}

ただし、一般的に、カプセル化ルールに違反するため、クラスのプライベート部分を返すことは非常に悪い考えです。そしてここでは、コードの呼び出しが配列の終わりの後ろで繰り返されてクラッシュするのを止めることはできません。境界チェックやオーバーロードgetImage(int i)演算子などの特定のアクセサー関数を作成する方がよいと思います。要約すると、私はこのコードを次のように書く方が良いと思います: setImage(int i, image *img)[]

class SlideShow
{
public:
    image *getImage(int i);
    void setImage(int i, image *img);
private:
    image *slideArray[10];
};

image *SlideShow::getImage(int i)
{
    if (i >= 0) && (i < 10)
        return slideArray[i];
    else
        // throw exception
}

void SlideShow::setImage(int i, image *img)
{
    if (i >= 0) && (i < 10)
        slideArray[i] = img;
    else
        // throw exception
}

注:setImageで、i番目の位置にすでに画像がある場合も考慮する必要がありますが、簡単にするために省略しました。

于 2012-08-23T08:48:00.827 に答える
2
image **SlideShow::getSlideArray()
{
    return this->slideArray;
}

おそらくうまくいくだろう

于 2012-08-23T08:23:45.417 に答える
1

標準C++ライブラリの使用を検討することをお勧めします:コンテナ(ex、std::vector)とスマートポインタ(ex、std::shared_ptr)。

ただし、生の配列を固定したい場合は、次のようにします。

class SlideShow {
public:
    image **getSlides() { return &slideArray_[0]; }
    std::size_t slideCount() { return sizeof(slideArray_)/sizeof(*slideArray_); }

private:
    image *slideArray_[10]; // Array of pointers to images.
};

クライアントコード:

SlideShow slideshow;

// Fill the slideshow here.

image** slides = slideshow.getSlides();
for (std::size_t i = 0; i < slideshow.slideCount(); ++i) {
    image *slide = slides[i];
}

このSlideShowクラスは、画像へのポインタの配列を画像へのポインタへのポインタとして公開します。配列のサイズを取得するには、クライアントコードでslideCount()メンバー関数を呼び出す必要があります。

于 2012-08-23T08:33:14.650 に答える