You have an array of 3 Shape*
variables, each pointing to a valid Shape
instance in the stack:
arr[0]
is pointing to thetri
instance, soarr[0][0]
is thetri
instance.arr[1]
is pointing to therec
instance, soarr[1][0]
is therec
instance.arr[2]
is pointing to thecir
instance, soarr[2][0]
is thecir
instance.
Any other use of arr
is basically illegal (even though it might work).
Although it is not recommended, the fact that the rec
instance and the cir
instance appear in the stack immediately after the tri
instance, allows you to use arr
in a few other ways and "stay alive":
arr[0][1]
is therec
instance, which appears in the stack after thetri
instance.arr[0][2]
is thecir
instance, which appears in the stack after therec
instance.arr[1][1]
is thecir
instance, which appears in the stack after therec
instance.
As pointed out in one of the comments below, it really depends on the implementation of the stack.
Any other (different) attempt to access memory through arr
is a potential memory access violation.
Here is how you should probably do it:
#include <string>
using namespace std;
class Shape
{
protected:
Shape() {}
virtual ~Shape() {}
string type;
int x,y,z;
public:
string GetType() const {return type;}
void SetX(int val) {x = val;}
void SetY(int val) {y = val;}
void SetZ(int val) {z = val;}
};
class Triangle : public Shape
{
public:
Triangle():type("Triangle") {}
void SetNum(int val) {tNum = val;}
private:
int tNum;
};
class Rectangle : public Shape
{
public:
Rectangle():type("Rectangle") {}
void SetNum(int val) {rNum = val;}
void SetDifferentNum(float val) {differentNum = val;}
private:
int rNum;
float differentNum;
};
class Circle : public Shape
{
public:
Circle():type("Circle") {}
void SetNum(int val) {cNum = val;}
private:
int cNum;
};
...
Triangle tri;
Rectangle rec;
Circle cir;
Shape* arr[3] = {&tri, &rec, &cir};
int size = sizeof(arr)/sizeof(*arr);
for (i=0; i<size; i++)
{
arr[i]->SetX(i*2);
cout << "set " << arr[i]->GetType() << "[" << i << "] = " << i*2 << endl;
}