?
Solved

passing array of objects as a function parameter

Posted on 2004-11-02
24
Medium Priority
?
2,297 Views
Last Modified: 2008-01-09
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
0
Comment
Question by:dkamdar
  • 6
  • 5
  • 4
  • +4
24 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 12477299
>>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
 

Author Comment

by:dkamdar
ID: 12477376
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
 
LVL 86

Accepted Solution

by:
jkr earned 1800 total points
ID: 12477438
>>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
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 

Author Comment

by:dkamdar
ID: 12478625
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
 
LVL 86

Assisted Solution

by:jkr
jkr earned 1800 total points
ID: 12479420
>> 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
 
LVL 15

Expert Comment

by:efn
ID: 12480570
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
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 12481472
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
 
LVL 17

Expert Comment

by:rstaveley
ID: 12482176
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
 
LVL 17

Assisted Solution

by:rstaveley
rstaveley earned 200 total points
ID: 12482263
Local function definitions (or "nested functions") are illegal in C++. GNU has them as a language extension.
0
 
LVL 86

Expert Comment

by:jkr
ID: 12484296
>> Local function definitions (or "nested functions") are illegal in C++

That's what I was referring to.
0
 
LVL 6

Expert Comment

by:SJT2003A
ID: 12584542
#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
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 12585314
>>>> 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
 
LVL 1

Expert Comment

by:okidachi
ID: 12640769
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
 
LVL 15

Expert Comment

by:efn
ID: 12640956
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
 
LVL 6

Expert Comment

by:SJT2003A
ID: 12644180
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
 
LVL 17

Expert Comment

by:rstaveley
ID: 12644718
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
 
LVL 6

Expert Comment

by:SJT2003A
ID: 12644806
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
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 12645450
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
 
LVL 6

Expert Comment

by:SJT2003A
ID: 12645629
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
 
LVL 17

Expert Comment

by:rstaveley
ID: 12646033
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
 
LVL 6

Expert Comment

by:SJT2003A
ID: 12646297
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
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 12646444
>> 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
 
LVL 17

Expert Comment

by:rstaveley
ID: 12646949
> 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
 
LVL 6

Expert Comment

by:SJT2003A
ID: 12647180
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

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.
Suggested Courses

839 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question