1

I have to use an array of pointers to Objects and I must also pass it as parameter to methods. However the way to do this eludes me. Here is the method I use for the initialization of the elements of the array. When I dereference them in main, their data are not correct (they contain memory addresses). What is the correct way? Might it be false the way I dereference them?

void createSquares(Square* squareArray[]){

    PropertySquare PropertySquare1(1,"purple",120);
    PropertySquare PropertySquare2(2,"purple",170);

    squareArray[1] = &PropertySquare1;
    squareArray[2] = &PropertySquare2;
.
.
.
}

In main:

Square *allSquares[22] ;
createSquares(allSquares);

cout<<"ID is: "<<allSquares[1]->getID()<<endl;
cin.get();

As I said the ID is finally a memory address.


Update based on answers:

I have tried this and it does not work as well.It is imperative for me to use polymorphism.

vector<Square*> allSquares;
createSquares(allSquares);

void createSquares(vector<Square*> &squares){

PropertySquare PropertySquare1(1,"purple",120);
PropertySquare PropertySquare2(2,"purple",170);

squares.push_back(&PropertySquare1);
squares.push_back(&PropertySquare2);

}

in main:

for (vector<Square*>::iterator it=allSquares.begin(); it!=allSquares.end();it++){
   it->
}

It does not allow me to use the virtual functions of Square since it is abstract. Any suggestion?

arjacsoh
  • 8,932
  • 28
  • 106
  • 166

3 Answers3

3

Everything you're doing is Not Good. It's tricky to figure out where to begin, so let me start at the end and present The Right Way:

typedef std::unique_ptr<Square> square_ptr;

void createSquares(std::vector<square_ptr> & v)
{
  v.emplace_back(new PropertySquare1(1,"purple",120));
  v.emplace_back(new PropertySquare1(2,"green",370));
  // ...
}

int main()
{
  std::vector<square_ptr> allSquares;
  createSquares(allSquares);

  for (const auto & p : allSquares)
    std::cout << "ID is: " << p->getID() << std::endl;
}

Now to break down your problems:

First off, you are storing the pointers of local variables. Those local variables die at the end of the function scope, and the pointers become dangling. Dereferencing is a program error.

Second, to fix this, you should create dynamic objects: squareArray[1] = new PropertySquare1(1,"purple",120); However, that is problematic, too. Someone will have to clean up those objects! You could iterate over the array and call delete on each element.

Third, 22 is a "magic number" (because it's neither 0 nor 1). This should not be hard-coded. If the number really is a compile-time constant, name it somewhere.

Fourth, either way, don't use raw arrays. Either use a std::array if the size is known at compile-time, or a std::vector if the size is determined at runtime.

Fifth, putting it all together, a dynamic container of smart pointers takes care of all your worries. That's the one presented in my code. The alternative, a static array of smart pointers, wouldn't use an initialization function at all, but rather it'd be initialized right on the spot:

const std::size_t nfuncs = 22;
std::array<square_ptr, nfuncs> allSquares {
  new PropertySquare1(1,"purple",120),
  new PropertySquare1(2,"green",370),
  // ...
};
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • You should mention that `emplace_back` is a new C++11 feature. In C++03, you'd need to use push_back with a copyable type (e.g. `boost::shared_ptr` because the only smart pointer in C++03, `std::auto_ptr`, cannot be used in containers). Anyway, `std::shared_ptr` might even be the right solution in C++11 since there might be the desired to be able to have copies of the pointers in the container (and if not, using pointers instead of values and `std::move` is probably just unnecessary overhead anyway). – celtschk Nov 27 '11 at 17:24
  • @celtschk: Yeah, so is `unique_ptr`, range-based `for` and uniform initialization :-) It's a bit more icky in C++03. I'll leave the shared-vs-unique debate to a later time when the OP has figured out what she wants. – Kerrek SB Nov 27 '11 at 17:26
  • Regarding your second remark: What about if the Objects are ever necessary while the program is running? Should I delete them in its last lines? – arjacsoh Nov 27 '11 at 20:58
  • @arjacsoh: Well, probably nobody is going to mind if you don't. Just be aware of what you've created, and be conscious of the fact that you kill them during shutdown. Personally I'd always clean up, though, since then you can use memory debuggers and always demand zero errors. – Kerrek SB Nov 27 '11 at 21:00
1

What is false is that

PropertySquare PropertySquare1(1,"purple",120);
PropertySquare PropertySquare2(2,"purple",170);

Are destroyed the moment createSquares returns. So your array contains junk when you print those IDs.

FailedDev
  • 26,680
  • 9
  • 53
  • 73
0

Because PropertySquare variables are declared in stack, they will be destroyed once the function returns. You want to declare them in heap instead by

squareArray[1] = new PropertySquare PropertySquare1(1,"purple",120);
squareArray[2] = new PropertySquare PropertySquare1(2,"purple",170);

and delete them in main by calling delete allSquares[1] etc.

JosephH
  • 8,465
  • 4
  • 34
  • 62