For starters, change your method listType::operator[] to return a listType object, not an apstring.
This way, when you do a list[1]="XYZ":
a) First it'll resolve list[1] as a listType object
b) Next it'll invoke the listType::operator= method.
Note: When you're assigning list[1] a value of "XYZ", you're really assigning it a char* value. However, given that your apstring class likely has a constructor which takes a char* value, the compiler creates a hidden temporary apstring object to pass to your listType::operator= method. A cleaner way to invoke the call is:
apstring temp="XYZ";
list[1]=temp; // Where now you're passing an actual apstring object to listType::operator=
*EDIT*
Actually, if you've already written your code such that you're depending on listType::operator[] returning an apstring, a quicker fix is to keep your code more or less AS-IS w/ one important change:
// Change the method prototype to return a REFRENCE to an existing apstring as follows:
apstring& listType::operator[](int num);
Note 1: You'll need to make that change both in your .h file (class definition) and your .cpp file (method implementation).
If your apstring class already has an operator= method (which it should), you don't need an additional operator= method in your listType class for what you're trying to accomplish. This should work; however, it's not the most appropriate way to code things.
Note 2: By returning a REFRENCE to an apstring, you're exposing the data attribute of a listNode object. This is IMO a violation of object oriented programming; however, as I said above, it should take care of what you're trying to accomplish