Returning an array of pointers?

12,348

Solution 1

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).

Solution 2

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.

Solution 3

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.

Solution 4

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

Would probably work

Solution 5

I would like to recommend you to consider using standard C++ library: containers (ex, std::vector) and smart pointers (ex, std::shared_ptr).

But if you would like to stick the raw arrays:

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.
};

Client code:

SlideShow slideshow;

// Fill the slideshow here.

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

The SlideShow class exposes the array of pointers to images as pointer to pointer to image. To get the size of the array, client code should call slideCount() member function.

Share:
12,348
MrKatSwordfish
Author by

MrKatSwordfish

Updated on June 26, 2022

Comments

  • MrKatSwordfish
    MrKatSwordfish almost 2 years

    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?

  • MrKatSwordfish
    MrKatSwordfish over 11 years
    Thanks! I think I understand now. Because my array holds pointers, if I want to return a single *image element, I have to specify a specific element of the array. But, if I want to return the entire array, I must return a pointer to a pointer.. - I have to ask a follow-up though: Why don't I need to use the 'this' keyword? Is it because any instance of a slideshow automatically knows to return it's own member? So, even if I have multiple SlideShow objects, each object has it's own copy of the function, and it 'understands' to return it's own member?? - (thanks for the help!!)
  • betabandido
    betabandido over 11 years
    When you are referring to a class attribute or method, most of the times the compiler is able to find the attribute/method that you are referring even if this is not used. In these cases this is just optional (i.e., there is no difference between using it or not). In other cases you actually need this. Check these other questions for some examples on when this is actually necessary: 1, 2.