Stan
Stan

Reputation: 26501

Return Array from Class

I need to return 3 values. X, Y, Z. I've tried something like this, but it does not work, can anyone help me a bit? I've looked here: Return a float array in C++ and I tried to do same thing, except with 1 dimensional array to return.

class Calculate
{
 float myArray[3][4], originalArray[3][4], tempNumbers[4];
 float result[3]; // Only works when result is 2 dimensional array, but I need 1 dimension.

public:
 Calculate(float x1, float y1, float z1, float r1,
  float x2, float y2, float z2, float r2,
  float x3, float y3, float z3, float r3)
 {
  myArray[0][0] = x1;
  myArray[0][1] = y1;
  myArray[0][2] = z1;
  myArray[0][3] = r1;

  myArray[1][0] = x2;
  myArray[1][1] = y2;
  myArray[1][2] = z2;
  myArray[1][3] = r2;

  myArray[2][0] = x3;
  myArray[2][1] = y3;
  myArray[2][2] = z3;
  myArray[2][3] = r3;

  result[0] = 1;
  result[1] = 2;
  result[2] = 3;
 }

 float* operator[](int i)
 {
  return result[i]; //Value type does not match the function type
 }

 const float* operator[](int i) const
 {
  return result[i]; //Value type does not match the function type
 }
};

Upvotes: 3

Views: 14506

Answers (5)

Chubsdad
Chubsdad

Reputation: 25497

Some responses have indicated the use of pointers. The problem is who allocates that pointer and who frees it. Also one needs to check if the incoming pointer is NULL and so on. Instead I would suggest the following declaration of the constructor.

 Calculate(float x1, float y1, float z1, float r1, 
  float x2, float y2, float z2, float r2, 
  float x3, float y3, float z3, float r3, float (&r)[3]) 

This is much more safer as references can not be NULL.

Upvotes: 0

Andrew Jaffe
Andrew Jaffe

Reputation: 27077

result[i] is a float, not a float*, so you can do

const float operator[](int i) const
{
  return result[i]; 
}

But I think you do want to return a reference to get the correct semantics, so you want

const float& operator[](int i) const
{
  return result[i]; 
}

float& operator[](int i)
{
   return result[i];
}

Right? (I think this is OK -- it compiles but it's been a while since I've done this...)

Upvotes: 2

Thomas Matthews
Thomas Matthews

Reputation: 57678

Another alternative is to make the result as a separate structure and either return it as a value or pass it by reference:

struct Result_Type
{
  double values[3];
// Alternatively:
// double x;
// double y;
// double z;
};

// Returning a result
const Result_Type calculate_result_1(/* yada yada yada */)
{
  Result_type new_result;
  new_result.value[0] = 0;
  new_result.value[1] = 0;
  new_result.value[2] = 0;
  return result;  // Return the result as a object
}

// Or passing a result to be modified
void  clear_result(Result_Type & any_result) // <-- Note pass by reference
{
  any_result.value[0] = 0;
  any_result.value[1] = 0;
  any_result.value[2] = 0;
  return;
}

You may find that this is a preferred design since you can pass around results, modify the Result_Type structure to perform operations with other result vectors (math term). The matrix can also be considered as a composition of result vectors.

This may make the code easier to read also.

Upvotes: 2

Reinderien
Reinderien

Reputation: 15221

Instead of returning a pointer, it's usually better practice to accept a pointer and write out the results there. That way someone can allocate a regular array on the stack and have it initialized by your Calculate.

Something like:

class Calculate
{
 float myArray[3][4], originalArray[3][4], tempNumbers[4];

public:
 Calculate(float x1, float y1, float z1, float r1,
  float x2, float y2, float z2, float r2,
  float x3, float y3, float z3, float r3, float *result)
 {
  myArray[0][0] = x1;
  myArray[0][1] = y1;
  myArray[0][2] = z1;
  myArray[0][3] = r1;

  myArray[1][0] = x2;
  myArray[1][1] = y2;
  myArray[1][2] = z2;
  myArray[1][3] = r2;

  myArray[2][0] = x3;
  myArray[2][1] = y3;
  myArray[2][2] = z3;
  myArray[2][3] = r3;

  result[0] = 1;
  result[1] = 2;
  result[2] = 3;
 }
};

Some other tweaks you can do - separate the constructor from the calculation, since constructors are more for initialization; and pass arrays for safer memory control:

class Calculate
{
    float myArray[3][4], originalArray[3][4], tempNumbers[4];

public:
    Calculate(const float initArray[3][4])
    {
        for (int i = 0; i < 3; i++)
            for (int j = 0; j < 4; j++)
                myArray[i][j] = initArray[i][j];
    }

    void DoCalculation(float result[3]) const
    {
        result[0] = 1;
        result[1] = 2;
        result[2] = 3;
    }
};

int main()
{
    float myArray[3][4] =
    {
        { 0, 1, 2, 3 },
        { 4, 5, 6, 7 },
        { 8, 9, 0, 1 }
    };
    float result[3];
    Calculate calc(myArray);
    calc.DoCalculation(result);
    return 0;
}

Upvotes: 5

UncleBens
UncleBens

Reputation: 41331

In the code, where you are getting an error, you are not trying to return a pointer. You are trying to return a single float at the given index.

Calculate c;
float first = c[0];
float second = c[1];
float third = c[2];

If you meant to return a pointer to the results array, then you would have to return the array, e.g

float* GetResult() { return result; }

It probably doesn't matter much which you'll keep because the end effect is pretty much the same. If you overload operator[], you'll have more control, though, as you can check out-of-bound accesses.

Upvotes: 0

Related Questions