Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning an array of pointers?

I'm a beginning programmer and I've been having quite a bit of trouble with C++ OOP. Specifically, tonight I was trying to write a simple class that takes in events and switches between multiple images, with a pointer to each image stored in an array. I ran into a confusing problem when trying to make a 'getter' function that returns a pointer to the array itself.

Basically, I was trying to do something like this:

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

So, I wanted to have an array that stores pointers to each image. And I also wanted to have a function that returns the address of the array itself. I ran into an issue when trying to define the getSlideArray() function... I'm just not entirely sure why it wasn't working...

Here's what I tried initially, in my class' source file:

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

In this attempt, the compiler kept raising issues with the use of the 'this' keyword, saying that what I was trying to return was not of the previously specified type. However, this is the way that I've been writing my getter functions up until now, and it generally works when using simple variables... My suspicion is that there is some problem here due to the fact that 'this' is a pointer, and 'slideArray' is a pointer to an array that also contains pointers... But I'm terrible and that level of referencing kind of goes over my head right now. It's been taking me a while just to gather a basic understanding of pointers, referencing using address & operator, etc. Pointers to pointers and arrays of pointers are even more confusing.

I should also mention that I found one work around, in which my code compiles. (Although I can't really run it to check and see if it works at runtime yet..) My work around involved adding the definition/return statement to the class declaration itself (inside the header file):

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

Now. This compiled correctly... BUT, it's also confusing to me. I know that generally, when you return an array (say, an array of ints), you are returning the address of the zeroth slot of the array. But if I was trying to return an intArray[5], when returning it, I would simply write 'intArray', correct? Essentially, I'm not confused as to why I have to add the * before 'slideArray' in this situation...

So no matter which way I try and do it, it's confusing me. I know that there is some 'trick' here, and that it probably has to do with returning pointers to pointers to pointers or something, but I just haven't been able to work it out myself. I really am hoping to learn this subject so that I can start to get a handle on programming, especially OOP...

Can anyone help me understand this better?

like image 383
MrKatSwordfish Avatar asked Aug 23 '12 08:08

MrKatSwordfish


3 Answers

The method definition that you are using:

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

states that a pointer to an image is being returned. However, you are trying to return an array of image. You should either do:

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

or

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

depending on whether you want to return all the images together (second option) or one by one (first option).

BTW, you do not need to use this at all. The next code is equivalent to the second option above:

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

The previous explanation should fix your issues. However, instead of using "raw pointers" and C-style arrays, you better to use STL containers (see @juanchopanza answer for that).

like image 93
betabandido Avatar answered Oct 05 '22 11:10

betabandido


I would use a standard library container of pointers or smart pointers, and return it (by value or reference, depending on your use-case).

for dynamic size:

#include <vector>

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

for static size (assuming C++11 support):

#include <array>

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

If you don't have C++11, try using std::tr1::array from header <tr1/array, or boost::array.

like image 24
juanchopanza Avatar answered Oct 05 '22 11:10

juanchopanza


Your first approach fails because you give bad return type in the function, you should use image**:

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

But generally, it's a very bad idea to return private parts of your class, as it breaks the encapsulation rule. And here, nothing can stop calling code from iterating behind the end of the array and crashing. I think it would be better to write specific accessor functions like getImage(int i) and setImage(int i, image *img) with boundary checks, or even overload [] operator. To sum up, I think it would be better to writ this code like this:

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
}

Note: you should probably also consider case in setImage where there already is an image on i-th position, but I ommited it for sake of simplicity.

like image 28
Alex1985 Avatar answered Oct 05 '22 12:10

Alex1985