?
Solved

Array of Pointers = Frustration

Posted on 2003-02-28
9
Medium Priority
?
316 Views
Last Modified: 2008-02-01
I have a program that works fine and it accepts a list of Animals and print each one individually.  The print function for one Animal accepts no parameters so it was easier for me to implement.  Now I have run into problems as I try to have a function that prints the entire list of Animal.  To do this I am trying to pass an array of pointers parameter into a  function called printlist.  Now my program wont compile and I receive errors like:

"error C2228: left of '.getName' must have class/struct/union type"

////////////////////////////////////////////////////////


I have declared a public function in class Animal by the following:

void printlist(Animal *[]); // I think this is right

I have defined the function in the implementation file like:
     
void Employee::printlist(Animal *anim1[])
{
       // MAX_ANIMALS = 100
     for (int x = 0; x <= MAX_ANIMALS; x++)      
     {
        cout << *anim1[x].getColor()  << "\t";
        cout << *anim1[x].getName() << "endl;
     }
}

In main I declared a pointer to a array like:

Animal *anim1  = new Animal[MAX_ANIMALS];


In main, I want to call printlist but how to I do that and pass in anim1...i.e. I know the following is wrong, but you can probably see that I want to print the array called anim1:

// to print all animals in the array of pointers
For (int x = 0; x <= MAX_ANIMALS; x++)
     anim1[x].printlist( anim1 );

///////////////////////////////////////////////////////


I'm now very sure that I don’t like pointers and arrays...I guess that makes sense since I don't understand them very well.  Too bad they are too important to give up trying to learn.  I have worked for 3 hours last night trying to make this program work.  Had all my books open and getting frustrated on how to accomplish this.  Can someone help me how to properly pass the parameters here so I can make my program execute properly and perhaps learn pointers and arrays once and for all.  Thanks so much for any help.
0
Comment
Question by:Invariant
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 3
  • 2
  • +1
9 Comments
 
LVL 8

Expert Comment

by:Exceter
ID: 8043054
>> Array of Pointers = Frustration

I think you meant,

Array of Pointers == Frustration

:-)

Anyway,

"error C2228: left of '.getName' must have class/struct/union type"

This usually means that you have attempted to access a pointer as you would a class, struct, or union. You can access the members of these types using the '.' character. For example,

myClass.getName();

However, if myClass is a pointer to the object the members are accessed like this,

myClass->getName();

Don't ask me why.

Exceter
0
 

Expert Comment

by:stefanq
ID: 8043104
Replace
> anim1[x].printlist( anim1 );
with
  anim1[x].printlist( &anim1 );

anim1 is an Anim1* pointing to the first element
of a field (array) of Anim1.
The first call passes this anim1 pointer.

But the printlist() method expects a pointer to
an anim1 array which is basically a Anim1** (pointer to
pointer of Anim).
You get this by taking the address of anim1

Alternatively it's also possible to change the argument in the definition of printlist() from "Anim*[]" to "Anim*" to pass the pointer to the first element of the Anim field.
Then the array elements can be accessed with "anim[x]" (instead of "*anim[x]").

Pointer syntax can get confusing at the beginning.
0
 
LVL 11

Expert Comment

by:bcladd
ID: 8043137
Excter-

Because it is much simpler to type classPtr->member() than it is to type (*classPtr).member() (the two expressions have the same impact for a class pointer). '.' binds tighter than (has higher precedence than) unary '*'


Invariant-

Why are you using an array of pointers?

Declaration of printlist inside of Animal doesn't make any sense. It would make much more sense to declare the function in the global namespace (where the array of Animals or Animal pointers exists) and leave Animal to deal with any single animal:

void printlist(Animal *anim1[])
{
      // MAX_ANIMALS = 100
    for (int x = 0; x <= MAX_ANIMALS; x++)      
    {
       anim1[x]->print();
    }
}

It might be easier to do this with the STL vector container. Just a thought.

-bcl

-bcl
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 8

Expert Comment

by:Exceter
ID: 8044107
bcladd, thanks for the clarification. :-)

Exceter
0
 

Author Comment

by:Invariant
ID: 8045190
Keeping all these tools straight in my mind and learning how to use them is not easy.

Exceter - Understood, and thanks.  That makes sense to me.

bcladd - Your suggestion of creating a global function probably makes the most sense (and it didn't even occur to me to do it).  Unfortunately I have not been introduced to vectors or STL vector container yet (I have seen some mention of this and will look at learning this).

stefang - Your comments about how to implement using a reference to anim1 ( &anim1 ) as the parameter is very well explained.

To follow-up on my understanding re. use of pointers and arrays in this situation

--> Using Animal as the object type and anim1 is the pointer to that object then are each of the following statements true?
1.  2Dim Arrays ~ Animal*[] is the same as saying Animal**.  Also, *anim1[] or anim* can be used to access either.

2.  2Dim Arrays - If I say Animal*[] then I can access elements of array anim1[] by saying anim1[x][y].
--->  FOLLOW-ON QUESTION :  IS THERE ANY OTHER WAY TO ACCESS ELEMENTS IN ARRAY anim1[][] (i.e. OTHER THAN BY USING anim1[x][y]).

3.  1Dim Arrays ~ Animal* is the same as Animal[] and anim1 can be used to access either (i.e. Animal* and Animal[] are not the same as saying anim1* because anim1 is already a pointer to an array of objects of type Animal).

4.  1Dim Arrays - If I say Animal* or Animal[] then I can access elements of array anim1[] by saying anim1[x].  ------->  FOLLOW-ON QUESTION :  IS THERE ANY OTHER WAY TO ACCESS ELEMENTS IN ARRAY anim1[] (i.e. OTHER THAN BY USING anim1[x])?

Thanks again to everyone posting their help.
0
 

Author Comment

by:Invariant
ID: 8046930
Hello bcladd (et al.),

I'm still battling over the problem and have tried techniques of both.  It is a different error caused as a result of this implementation, otherwise I would have posted a different question in the forum.

I added code to try and implement the global namespace suggestion but have started receiving an "Unhandled Exception...Access Violation” error.  I am having trouble determining the cause of my error and wondered if you can suggest anything here.

My program complies and runs, but after adding code shown below in order to try and print a list of items I started to see this new error.  The code I added was a global function to print the data for each animal in the array of anim1 objects.

****************************************************

void printlist(Animal *[], int);   // prototype – function in global namespace

int main( )
{
Animal *anim1  = new Employee[100]; // array declaration
.
...//in here I fill the array of objects of type Animal and it works fine
.
.
printlist(&anim1, count);  // call to function printlist; count is the # of objects in the list
.
.
delete [] anim1;
}

void printlist(Employee *Animaltype[], int counter)
{
   for(int x = 0; x <= counter; x++)      
   {
      // print is a function I use to just print one item.
      // print1() is shown below.
      Animaltype[x]->print1( void );  
   }
}

// class member function included for information purposes (in case it helps).
void Animal::print1(void)
{
     cout << "Animal ID #:\t" << idNum << endl;
     cout << "Animal Name    :\t" << getName() << endl;
     cout << "Animal Color:\t" << color << endl;
}
*************************************************

What happens is, no matter how I change the method of passing parameters etc. the first time through the print1() function I get output of the Animaltype[0] array item; but, the second pass through the for loop is when I get the “Unhandled Exception....Access Violation” error.

Can anyone help me figure out why I receive such an error?  I’ve never come across it before although from the research I’ve done it seems to be caused by unauthorized memory access.  Unfortunately, knowing why it CAN happen hasn’t helped me to solve what the real cause of the error is.
0
 
LVL 8

Expert Comment

by:Exceter
ID: 8047520
Are you using MSVC++? If so, you should use its debugger.

Exceter
0
 
LVL 11

Accepted Solution

by:
bcladd earned 200 total points
ID: 8047710
(1) Animal[] is _almost_ the same as Animal*:
- Both can use the [x] notation for referencing contiguous elements of an array
- Animal* can be modified; Animal[] cannot:

  Animal A[10];
  Animal *p = A; // legal since an array is an address
  p[0] = /* some Animal expression */;
  *p = /* some Animla expression; same as above */;
  A[0] = /* same as above */;
 
  p = p + 1; /* moves the pointer to point at A[1] */
  *p = /* some Animal expression; sets A[1] */

(2) The error you describe is caused by the <= in the for loop inside print. You are accessing an uninitialized location in memory.

(3) I don't think a pointer at an array is what you want to pass. It makes more sense to pass in an array directly:

  print(Animal[], int);
  Animal anim1[100]; /* no need for new if the size of the array
  is compile time constant; this doesn't create Employee objects. */
  ...
  print(anim1, count);

  void print(Animal[] A, int count) {
  // count is # of entries in A; one bigger than largest
  // element index in A
    for (int i = 0; i < count; ++i)
      A[x].print();
  }

I am trying to remove pointers where possible to make your code simpler. Note that you need pointers if you are using inheritance. If that is the case, the above can be modified as follows:

  typedef Animal * AnimalPtr;
  print(AnimalPtr[], int);
  AnimalPtr anim1[100]; /* no need for new if the size of the array
  is compile time constant; this doesn't create Employee objects. */
  ...
  print(anim1, count);

  void print(AnimalPtr[] A, int count) {
  // count is # of entries in A; one bigger than largest
  // element index in A
    for (int i = 0; i < count; ++i)
      A[x]->print();
  }

Only real change is that the array elements are pointers so you use -> rather than . to access print function.

Hope this helps, -bcl
0
 

Author Comment

by:Invariant
ID: 8050606
Hi,

Just wanted to tell you that I was able to get everything working today.  

I used the function declaration in global namespace:
--> void printlist(Animal[], int);  // function declared

I used a dynamic array:
--> Animal *anim1 = new Animal[MAX_ANIMALS);

I called function printlist from main:
--> printlist(anim1, (count+1))

I defined function printlist after main:
--> void printlist(Animal *E, int count)
    {  for(int x = 0; x < count; i++)
          E[x].print(void)    // where print is defined in the class
                              // implementation file and prints just one animal
    }


Thanks again for all your help, it was very helpful and valuable to me to understand pointers and arrays.  I really appreciate the help from those of you who have experience and are willing to share it with others like me....I know your own time is valuable too.
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

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

  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
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

764 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