3

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
 }
};
1
  • Should probably be &result[i]. Commented Sep 24, 2010 at 15:12

5 Answers 5

5

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;
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, worked great, even better because it takes less code.
Note that passing pointers is not generally considered a better practice in C++, but then, neither is returning pointers to internal members of a class.
@jkerian, Yup; this is why I prefer the approach by @Thomas Matthews.
2

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.

1 Comment

+1 except for one thing: I would not put an array in the struct, but three seperate values (of which each has its own meaning, like x, y, and z for example).
2

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

Comments

0

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.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.