passing array of objects as a function parameter

Hi,

heres the situation:

Class A {
public
void setm1();
void setm2();
};

int main()
{
 //protoype of function loadA
 void loadA (A &a, const long i);
 
 // making an array of objects of type A
 A *m = new m[10];
 const long x = 5L;
 // calling load A
 loadA (m,x);

 //definintion of function loadA
 void loadA (A &a, const long i)
 {
   for (some condition)
   {
    a[i].setm1(); //set m1 for ith object in array a
    a[i].setm2(); //set m2 for ith object in array a
   }
 }
}

---------------------------------------------------------

in words, i am trying to pass an array of objects in a function. function should index each object in a for loop and call methods for that object to load that object. in above case i need to pass a reference to array of objects m of type A and load all the variavbles for all objects in m.

while trying to do it in the above way, i get compilation errors. Please suggest me how can I do this task.

Its urgent.

Thanks
dkamdarAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jkrCommented:
>>while trying to do it in the above way, i get compilation errors

You have several errors in you code, that should be more like

Class A {
public
void setm1();
void setm2();
};

//protoype of function loadA
void loadA (A* a, const long i); // cannot be inside 'main()' and it needs to be 'A*'

int main()
{

 // making an array of objects of type A
A *m = new A[10]; // not 'new m', but 'new A'
const long x = 5L;
// calling load A
loadA (m,x);
}

//definintion of function loadA
void loadA (A* a, const long i)
{
  for (some condition)
  {
   a[i].setm1(); //set m1 for ith object in array a
   a[i].setm2(); //set m2 for ith object in array a
  }
}
}

0
dkamdarAuthor Commented:
Hey jkr,
In this case you are passing a pointer to the object.
I need to pass a reference.
Can you please modify the calling if the function prototype has to look like this i.e. I have to pass a reference and I not a pointer.
void loadA (A &a, const long i);

And why cannot the protoype be inside main?

Thanks
0
jkrCommented:
>>In this case you are passing a pointer to the object.
>>I need to pass a reference.

Then, you should pass the reference to the element from 'main()' and not the whole array or a reference to the array, e.g.

// method 1 - reference to the array

Class A {
public: // ':' was missing
void setm1();
void setm2();
};

//protoype of function loadA
void loadA (A& a[], const long i);

int main()
{

 // making an array of objects of type A
A *m = new A[10];
const long x = 5L;
// calling load A
loadA (m,x);
}

//definintion of function loadA
void loadA (A& a[], const long i)
{
  for (some condition)
  {
   a[i].setm1(); //set m1 for ith object in array a
   a[i].setm2(); //set m2 for ith object in array a
  }
}
}

// method 1 - reference to an element

Class A {
public: // ':' was missing
void setm1();
void setm2();
};

//protoype of function loadA
void loadA (A& a);

int main()
{

 // making an array of objects of type A
A *m = new A[10];
const long x = 5L;
// calling load A
loadA (m[x]);
}

//definintion of function loadA
void loadA (A& a)
{
  for (some condition)
  {
   a.setm1(); //set m1 for ith object in array a
   a.setm2(); //set m2 for ith object in array a
  }
}
}

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Cloud Class® Course: MCSA MCSE Windows Server 2012

This course teaches how to install and configure Windows Server 2012 R2.  It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

dkamdarAuthor Commented:
can you please tell why can i not protoype the function inside main? Because its a global function for this file?

Please lemme know

Thanks.
0
jkrCommented:
>> can you please tell why can i not protoype the function inside main?

If you declare the function inside 'main()', it would be a function that is local (and therefore only valid) inside 'main()', and C/C++ simply does not support that. It's 'illegal'.
0
efnCommented:
I haven't been able to prove this by the standard, but I believe it is legal to declare a function inside another function.  The linkage is still external by default, but the scope is local, that is, the function name would not be known in other functions.

At least three compilers accept such declarations and a couple of other (non-authoritative) guys support this view implicitly in their examples.

http://www.mattababy.org/~belmonte/Teaching/CCC/CrashCourseC.html

http://publications.gbdirect.co.uk/c_book/chapter4/function_types.html

This Usenet discussion takes it for granted that local function declarations are legal and debates whether this is a desirable language feature or not.

http://groups.google.com/groups?hl=en&lr=&threadm=G2erc.580%24_o.152%40fed1read05&rnum=1

--efn
0
itsmeandnobodyelseCommented:
Make load() a member and you don't need a separate prototype

class A {
public
   void setm1();
   void setm2();
   void load();
};

int main()
{
    // making an array of objects of type A
    A *m = new A[10]; const long x = 5L;
    for (int i = 0; i < 10; ++i)
        a[i].load();
}

//definintion of function load
void A::load ()
{
    setm1(); //set m1
    setm2(); //set m2
}


Regards, Alex

P.S.

The following compiles in VC6

int main(int nArg, char* pszArgs[])
{  
    void deldir(const char* szDir);
    if (nArg == 2)
        deldir(pszArgs[1]);
    return 0;
}

void deldir(const char* szDir)
{
    ...
}

0
rstaveleyCommented:
There's nothing wrong with prototyping locally. The ability to do this is why no code is generated by x1...

int main()
{
      foo x1(); /* Prototypes a function returning an object of class foo called x1  */
      foo x2; /* This constructs an object of class foo called x2, using the default constructor */
}

I notice that Visual C warns you about this though, because it is such a common mistake to think that x1 is constructed using the default ctor too.
0
rstaveleyCommented:
Local function definitions (or "nested functions") are illegal in C++. GNU has them as a language extension.
0
jkrCommented:
>> Local function definitions (or "nested functions") are illegal in C++

That's what I was referring to.
0
SJT2003ACommented:
#include <iostream.h>

class A {
public:
void setm1();
void setm2();
};

//protoype of function loadA
// SJT A * &a  declarea a referenced pointer to A type, so that loadA() does not create any local pointer var for  passed-in 'a'
void loadA (A * &a, const long i);   // SJT should be outside any other function (ie. global for the program)

int main()      // SJT main() itself a functon, can not have a prototype declared or function defined in
{
 
 // making an array of objects of type A
 A *m = new A[10];    // SJT A is a type, but not m. m is just a pointer variable, so it should be an array of A type
 const long x = 5L;
 // calling load A
 loadA (m,x);

 return 0;  // SJT added as main() delcared with a return type int
}
 //definintion of function loadA
 void loadA (A * &a, const long i)    // SJT a function can not defined within another functon, should be a separate one
 {
   for (int x=0;x<i;x++)
   {
    a[i].setm1(); //set m1 for ith object in array a
    a[i].setm2(); //set m2 for ith object in array a
   }
 }

0
itsmeandnobodyelseCommented:
>>>> void loadA (A * &a, const long i)    

Couldn't see any substantial difference to jkr's

      void loadA (A& a[], const long i);

Regards, Alex

0
okidachiCommented:
Hello,

I copied the code above from jkr for the accepted answer and compiled it with VC++ 6.0 .. But why it gives the compilation error :"error C2234: '<Unknown>' : arrays of references are illegal..."

Is there something wrong here or did I forget to turn on some features in VC++ ?
0
efnCommented:
jkr wrote:

"Then, you should pass the reference to the element from 'main()' and not the whole array or a reference to the array, e.g...."

Then he provided two implementations, of which the first was labeled "method 1 - reference to the array".  It actually has an array of references, but from the previous statement, it looks like this was intended as an example of what not to do anyway.  I think he was recommending the second method 1, "reference to an element".

In any case, the compiler is right:  arrays of references are illegal.  And jkr's second implementation does not use one.

--efn
0
SJT2003ACommented:
Hi Alex (itsmeandnobodyelse),  

There is a difference between a 'reference' and 'pointer' in C++ terms. In jkr's suggested solution the parameter 'a' is delcared as an array of references to Class A type, where in mine, 'a' is a pointer to Class A type but passed-by reference.
In jkr's, the parameter 'a' itself declared as a reference in the function prototype, where in the one I suggested, 'a' is a pointer but passed by reference. Since the argument 'm' in the calling function is declared as    A *m      and it points to a valid memory address allocated by 'new', the receiving parameter should also match its type. And the user wants pass the pointer by reference (rather than by-value (just an address)), the suggest prototype/function-heading  enables the caller function to passs its argument in by reference. So it avoids a compilation error too, if any. Hope you got my point.

Would be happy to give you more details, if you like.
Good day :)
0
rstaveleyCommented:
Arrays of references are illegal. I'd expect the compiler to grumble about jkr's void loadA (A& a[], const long i).

However, arrays are "passed by reference" (as the C folk say) anyhow, which means that an array passed as a function parameter is indistinguishable from a pointer. You can even increment the pointer, which is something that makes C++ heads spin, because a "reference" is something whose address cannot be changed.

--------8<--------
#include <iostream>

//void f1(int& array[]);  // Illegal
void f2(int array[]);
void f3(int *array);

int main()
{
      int array[] = {1,2,3};
      //f1(array);
      f2(array);
      f3(array);
}

//void f1(int& array[])
//{
//      for (int i = 0;i < 3;i++) {
//            array[i] *= 2;
//            std::cout << array[i] << '\n';
//      }
//}

void f2(int array[])
{
      for (int i = 0;i < 3;i++) {
            array[i] *= 2;
            std::cout << array[i] << '\n';
      }

      // You can even do this!! i.e. It is a pointer really!!
      std::cout << *(++array) << '\n';
}

void f3(int* array)
{
      for (int i = 0;i < 3;i++) {
            array[i] *= 2;
            std::cout << array[i] << '\n';
      }

      // It should be no surprise that you can do this
      std::cout << *(++array) << '\n';
}
--------8<--------
0
SJT2003ACommented:
rstaveley ,
you are absolutely right and I totally agree with you. Using array of references (& operator in the function headings ) is not recommended and not a good style of programming.
Rather, it would be better if used a pointer instead of reference, when its counter-part argument is also a pointer.

Good day :)
0
itsmeandnobodyelseCommented:
Hi SJT2003A,

when passing an array to a function, there is *no* difference passing it as array or as pointer type. So,

      void f(A* a)  and  void f(A a[])

are equivalent. Same should be expected when using a reference type. However,

     void f(A& a[])

doesn't compile (arrays of references are illegal). The reason is, that the compiler associates the reference symbol '&' to A type rather than to the array. So, the argument of jkr's sample function was wrongly defined (efn already found out) and the correct approach is using a pointer reference as you did.

So, in one regard, i was wrong, as i didn't recognized that your solution was compilable and jkr's was not. But beside of that, i still can't see any substantial difference.

Regards, Alex




0
SJT2003ACommented:
Alex,
 
 There is not much difference in a simple conding perspective. But it is not recommended I said. As you said, its right when an array is passed by reference  the passed-in (pointed to) allocation can be accessed as an array in the called function. It works perfect with a C compiler. But, it would not be suitable always as C++ provides already a reference type operator and allows different kinda objects to pass back and forth.
So it is always recommended and it would be error-free when both  calling-arguments and passed-in-parameters are of same type, especially when the code is compiled with a C/C++ compiler. Hope you got my point.

Good day :)
 
0
rstaveleyCommented:
The trouble with

    void loadA (A * &a, const long i);   // SJT should be outside any other function (ie. global for the program)

is that it empowers loadA to change the pointer passed to it

    A *p = new A[10];
    A *p2 = p;
    loadA(p2,10);                  // Signature makes me think that...
    assert(p == p2);             // ...this assertion may not be right

which I suspect isn't something you want to do.

It doesn't implicitly promise that p2 will continue to point to p in the calling code
0
SJT2003ACommented:
Nope, p and p2, both should point same address as long as the loadA function does not change the content of  referenced/pointed by  'a' in the loadA function.
To be clearer, you are first declaring a pointer called 'p' with an allocation of 10 A class objects and copying the same address to p. So p and p2, both, will point at same address.
And in the loadA(), the function-heading enables the program to manipulate the content stored in the allocated address without creating a new local variable for the pointer 'a' in the loadA() function which is actual concept of the 'reference'.

For example.
 A *p = new int[10]; //array of 10 integers
// just as an exmaple,assume p is pointer variable created at address 0x100 and holds the allocated memory address 0x1001 which is the beginning of array of 10 integers; which means, p is a name for the memory location 0x100
loadA(p);  // call the function now
 
while
loadA(int *param1)   // allocates a new local variable called param1 at different (from 0x100) address but holds the same value 0x1001. For example, assume the local pointer param1 is created at 0x120. Means, param1 is a name for the memory location at 0x120 but contains the copied content 0x1001.

but if you declare loadA()   as
loadA(int * &param1) // does not create a new varibale but access the content at 0x1001 by  different name, param1. That means,   'p' in the calling function and 'param1' in the called function are two names for same memory location 0x100. If you change the content of param1  ( like param1++) then it would obviously change the value of 'p' in the calling program also, like 102 (ie, an integer holds two bytes, so a ++ increments to next available address incremeted by 2).  

Got it?
0
itsmeandnobodyelseCommented:
>> Hope you got my point.

Actually not, as now you are speaking of differences between pointer type and reference type now, what indeed is a big difference, but is not the issue of our discussion. Also, in C arguments cannot be passed by reference, but only by value or by pointer.

What i (and others: efn, rstaveley) try to point out is, that in C and C++ there is no array type that could be passed as an argument, but it is a pointer, whether you declare it like

    void f(A* a);

or

    void f(A a[]);

That isn't a technical view only, but it is also logically the same.

Look at that function:

class A
{
    int a;
public:
    A() : a(0) {}
    A(int i) : a(i) {}
};


void f (A a[])
{
  int s = sizeof(a);
  for (int i = 0; i < 100; ++i )
  {
      a[i] = i; //set m1 for ith object in array a
  }
}

int main()
{
    A*  arr = new A[100]; // pointer variable
    f(arr);                         // passed as *array*
    return 0;
}

Here

   int s = sizeof(a);

evaluates to 4, so actually the argument of

    f(A a[])

is a pointer pointing to the first array element and *not* an array passed by value.

When passing a pointer by reference, the called function could replace the given pointer by a new pointer variable as rstaveley told. That could make sense if you want to pass a NULL pointer that should be replaced by a valid array pointer. The return value in these cases most often is the size of the array. But, i agree with rstaveley that in most cases passing a non-const reference isn't recommendable. An alternative to that is using class member functions that are operating on class members rather than on arguments passed by reference.

Regards, Alex
0
rstaveleyCommented:
> Nope, p and p2, both should point same address as long as the loadA function does not....

That assessment requires knowledge of the loadA implementation. You wouldn't guess that from the prototype. To an experienced C/C++ developer the function signature doesn't underline the fact that the variable is being passed by reference, it suggests that the pointer is going to me changed.

Also, beware that it is something that couldn't be used with a static or automatic array.

e.g.

        A arr[100];
        loadA(arr,100);        // Compile error: A reference that is not to 'const' cannot be bound to a non-lvalue
0
SJT2003ACommented:
Alex, seems you got the point I was talking about.
As rstavely also said, it empowers the called function to change the referenced pointer and you agree it is good when a NULL pointer is passed-in and it needs to be replaced with a valid address as needed.
I agree using non-const reference should be used as needed but having full knowledget of what the called function could do with it. It all depends upon the design of program. It should be used carefully and when only needed.
And about my initial post was about using "same type for parameter and argument is always recommended". Replacing a * (pointer) with & (reference) is no good idea.
Good day :)
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.