C++ pointers to class members

I’ve looked at the C++ FAQ and other places, such as this answer and the surrounding answers in that section, and I can’t seem to figure out how to do what I want. I’m using gnu C++ on a Linux box.

I’m trying to create an simple simulation of a Linux scheduler – it was a homework lesson last semester that I couldn’t do at all, and got a 0 on, but it’s irritating me no end and I’ve been working on and off on it for months. I’ve created a couple classes: proc, which includes a bunch of data objects that are information about a process, including its priority, and another class called priority_array that includes 13 queues – these are just standard C++ queues using the

#include <queue>

header, and to define them I’ve done

queue<proc> queue0;
queue<proc> queue1;
queue<proc> queue2;
queue<proc> queue3;
queue<proc> queue4;

queue<proc> queue13;

Now, each process can have a priority level from 0 to 139. Processes with priority 0-9 will go into queue0, 10-19 will go into queue1, and so forth, up to .

So I was working on an add() function, to add each process to the priority array, and obviously if I had an array of pointers to the above queues, I could just apply a simple “Put it in queue int(priority/10)” rule. Say the array was called which_queue, and a pointer to queue0 was in which_queue[0], pointer to queue1 in which_queue[1], etc., then I could just do:

which_queue[(int)priority/10].push(whatever_process);

(or which_queue[(int)priority/10]->push(whatever_process), depending on whether I need the . or -> operator in this case)

to add the current process to its queue. But since queues themselves are a class … and I’ve created queue objects in my priority_array class … and I’m trying to access those objects from a member function of the priority_array class … I don’t know how to do it. This many levels of classes is just confusing the hell out of me.

Can anybody tell me what I need to do to make this kind of thing work? It would be handy in a lot of other situations too.

I’ll take a shot.

The problem you’re running into is essentially that you’re trying to “work around” the whole point of your priority_array class - you are trying to access directly that which you are intending to “encapsulate” with the class.
Put another way, you’re trying to use (old school) direct array access to member variables that you should essentially be “hiding” with the priority_array class.

First (to do what you want, but not the best OOD):
You could create a function for your priority_array class:
queue* GetQueuePtr( int priority );
This would return the pointer to the appropriate queue based on the priority. You would then do your ->push on the returned object.
However, this is kind of “exposing” your queue member objects. And not the best OOD.

Preferred OOD approach:
create a function for your priority_array class:
bool AddTasktoQueue( int priority, process_type whatever_process);

INTERNALLY you can have a queue* array which contains pointers to your queues:
queue* _queuePtrs[ NUM_QUEUES ];
(you would need to initialize this with the appropriate pointers)

And then this AddTasktoQueue function would do the priority/10 to determine the index (good to add some range checking here), and then do the ->push on the appropriate queue.

This approach “hides” the details of 1) how many queues, 2) the relationship of priority to which queue from the outside world. Should any of these characteristics change, there would be no need to change any of the outside world code - you would always call “AddTasktoQueue” in the same manner.
(Note: the GetQueuePtr approach would also shield the outside world from any characteristic changes as well. But again, this “exposes” the queues too directly. It would be preferrable for the outside world to not have direct access to the internals of the priority_array object).

Why don’t you make an array?

vector< queue<proc> > which_queue;

and then your statement

which_queue[(int)priority/10].push(whatever_process);

will work fine.

Yep, that’s what I ended up doing, about ten minutes after I posted this thread. <slap forehead> Oh well, maybe somebody else will be in this position someday and can find this thread.

Oh, and then I further simplified it by making it a vector of queues of integers, and just using the PIDs pointed to by the integers to manipulate the proc objects directly.

If only I had thought of it a few hours earlier, I wouldn’t have wasted so much time…

BTW, thanks, cormac, for your solution. I’ll have to study it in detail to see if I can understand it.

Making the array (instead of your priority_array class) to “hold” the queues un-does the point of your priority_array class. That is, instead of your priority_array object encapsulating the queues, you’ve “exposed” them to the world (the rest of the code).

The solutions I presented were an attempt to preserve your priority_array object (a good thing).

By exposing the queues, you now “push” the access to these queues to the rest of the code - instead of containing/limiting the access via your priority_array object.
So now every access to the queues might need to be modified should the characteristics (containing only 10 priorities each, for example) ever change. How many places in the code might need to be modified ? If it’s more than one then it justifies containing that logic.

I sense you are in the “get it to work - don’t mind the aesthetics” mode. But think about it for a bit. You were on the right (OOD) track with your priority_array object. You shouldn’t abandon it merely to be able to use array indexing access to your queues.

The vector of queues is defined inside the priority_array class definition. It’s not publicly accessible – I wrote a method inside the priority_array called add() to add a process which is given the PID and the priority and does the work of actually adding that number to the right queue.

Which is what I suggested originally:
Preferred OOD approach:
create a function for your priority_array class:
bool AddTasktoQueue( int priority, process_type whatever_process);

INTERNALLY you can have a queue* array which contains pointers to your queues:
queue* _queuePtrs[ NUM_QUEUES ];
(you would need to initialize this with the appropriate pointers)

Good job !