Hi,

I'm trying to create an array or <list> of different objects ( of different type).

All of the objects will have parent objects of a Manager type, but each one ( as a singleton) will be in the array/list.

It's for some networking code I'm building, where each incoming message over the network is "given" to a manager - and the panager then acts on it ( or drops it if irrelevant)... so:

For each manager in manager_list:
manager_object->run(message);

sort of thing.


Is this possible/how could I achieve it, or what would an alternate model be?

Thanks,
PC_Nerd

Recommended Answers

All 8 Replies

Hi,

I'm trying to create an array or <list> of different objects ( of different type).

All of the objects will have parent objects of a Manager type, but each one ( as a singleton) will be in the array/list.

It's for some networking code I'm building, where each incoming message over the network is "given" to a manager - and the panager then acts on it ( or drops it if irrelevant)... so:

For each manager in manager_list:
manager_object->run(message);

sort of thing.


Is this possible/how could I achieve it, or what would an alternate model be?

Thanks,
PC_Nerd

Are all of the objects you wish to store derived from the same base class? If so you could try creating a standard library list (or deque or vector or whatever you feel is appropriate) containing objects of the base type...If you catch my drift??

e.g. You have a base class called ManagerObject, and several different types derived from ManagerObject,(I'll call them ManagerObjectTypeA, ManagerObjectTypeB, ManagerObjectTypeC.)

You could then create a std::list of ManagerObjects (std::list<ManagerObject>) which you could populate with anything derived from ManagerObject (in other words your ManagerObjectTypeA, B or C objects), as technically they are still ManagerObjects.

Then when it comes to retrieving the objects from the list, you'd have to dynamically cast them to determine their final type (i.e. whether they were type A, B or C).

I don't know if that is in any way helpful, or if it's quite what you're looking for, but it's a technique I've seen used in the past!

Cheers for now,
Jas

That sounds very helpful - if it werent for the fact I'm not sure what you mean by "dynamic cast" when I need to retreive the object back out again.

As their singletons I'll probably be storing pointers in there, and not the actual objects themselves.

Thanks heaps!!!!

That sounds very helpful - if it werent for the fact I'm not sure what you mean by "dynamic cast" when I need to retreive the object back out again.

As their singletons I'll probably be storing pointers in there, and not the actual objects themselves.

Thanks heaps!!!!

No probs!
If you're storing pointers, then this certainly would be ideal.
To dynamically cast you use the dynamic_cast operator, there's shedloads of help on dynamic_cast on the web...Do a quick google and you'll find plenty of info!!

Basically it's a type-safe way of casting objects at runtime.
A successful cast will return a pointer to the chosen object type, but if a dynamic cast fails, it returns a null pointer..So if casting to one type fails, you can try casting it to a different type until you finally determine the objects type.

If memory serves correctly, I think you also need to ensure that the base class has at least one pure virtual function.

(Normally I would've included some code, but I'm not on my dev machine at the mo, so I don't have any relevant source code to refer to or pull up and copy/paste!)

Jas.

ok - so this is my first even STL implementation (sort of)... so is this the sort of thing I'm looking for?

class Manager {
    protected:
        virtual int run(string msg);
}
class PingManager : public Manager {
    protected:
        int run(string msg) {
                std::cout << msg << std::endl;
                return 0;
       }
}

main() {
    PingManager ping;
    list<Manager> myManagers;
    myManagers.push_back(Manager* p &ping);
    .... later in my program
    Manager* mngr = dynamic_cast<Manager*>(myManagers[0]);
    mngr->run("my Message");
}

I'm just trying to make sure I'm understanding what is going on - as I've only just got my head around pointers and references ;)

Thanks for help!,
PC_Nerd

ok - so this is my first even STL implementation (sort of)... so is this the sort of thing I'm looking for?

class Manager {
    protected:
        virtual int run(string msg);
}
class PingManager : public Manager {
    protected:
        int run(string msg) {
                std::cout << msg << std::endl;
                return 0;
       }
}

main() {
    PingManager ping;
    list<Manager> myManagers;
    myManagers.push_back(Manager* p &ping);
    .... later in my program
    Manager* mngr = dynamic_cast<Manager*>(myManagers[0]);
    mngr->run("my Message");
}

I'm just trying to make sure I'm understanding what is going on - as I've only just got my head around pointers and references ;)

Thanks for help!,
PC_Nerd

You've almost got it...At line 30 you'd need to do this though:

PingManager* mngr = dynamic_cast<PingManager*>(myManagers[0]);

because you'll be wanting to retrieve your pointer to your pingmanager.
and before calling mngr->run("My Message") you'd want to verify the pointer returned by the dynamic cast was not null! i.e.

if (mngr)
    mngr->run("My Message");

Once you've got several diffferent types of manager object defined and stored in your list, it could get a bit complicated as you may have to perform several dynamic casts before you get back to the original type.

Once it gets to that point, something you could consider doing is creating an enumeration of the different types of manager objects, create a std::pair consisting of your manager pointer and its associated enumeration and then store the pairs in the list. Then when you retrieve each pair, you check the enumerated value and then use that to determine which dynamic cast operation you have to perform..Damn..Battery running low..Gonna have to continue this another time! Sorry! J.

Thats fantastic- thanks for that!

I haven't really looked into enums yet so I'll have to explore that once I start getting more than one manager ( because as I said these managers are singletons, so every element in my managers list will be of a different type.... I'll post if Ive got any queries on the enum method...


Thanks again,
PC_Nerd

EDIT: another question: can I use the run() method directly from the list, instead of creating that pointer to the object first?

Thanks

Thats fantastic- thanks for that!

I haven't really looked into enums yet so I'll have to explore that once I start getting more than one manager ( because as I said these managers are singletons, so every element in my managers list will be of a different type.... I'll post if Ive got any queries on the enum method...


Thanks again,
PC_Nerd

EDIT: another question: can I use the run() method directly from the list, instead of creating that pointer to the object first?

Thanks

You mean something like myManager[0]->run(); ?
Yes, I think that might be possible...

However, thinking about it.. As all of these objects are singletons; to avoid having to mess around with dynamic casting, I suppose you could just put a public static GetInstance() method into each of your manager classes (if it's static then it can be called from outside of the class). The GetInstance function would then return a pointer to the instance of the required manager class.

If you know where each of the manager objects are in the list, then you could just reference the list item for each class and your GetInstance could return the pointer that way.

Actually, ignore all of that....You probably don't need the list at all come to think of it. You could perhaps store the instance pointers in each manager classes namespace and use a GetInstance function...

Something like this...
PingManager.h:

//headers, preprocessor, inclusion guards etc to go here

class PingManager : public Manager
{
protected:
    virtual int Run(string msg);
public:
    PingManager();
    ~PingManager();
    PingManager* GetInstance();
};

PingManager.cpp:

// includes and preprocessor stuff goes here
#include "X:/path/PingManager.h"

// local unnamed namespace 
// that way only members of Pingmanager can acces the mgr_instance ptr.
namespace
{
    // pointer to the instance
    static PingManager* mgr_Instance;
}

// constructor
PingManager::PingManager()
{
}

// destructor
PingManager::~PingManager()
{
        if(mgr_instance)
            delete mgr_instance // delete instance!
}

int PingManager::Run(string msg)
{
         // do whatever it does!
}

static PingManager* PingManager::GetInstance()
{
    // if there isn't already an instance, then create one! 
    if(!mgr_instance)
        mgr_instance = new PingManager();
    else // return the existing one...
        return m_instance;
}

If there is no instance found of the PingManager, a new one will be created. So now there's no need to create an instance of the PingManager...The first time you try to use PingManager::GetInstance(), the mgr_instance variable will be null and so mgr_instance will be populated by a pointer to a new instance. All subsequent calls to GetInstance will return the pointer as per normal..

eg.

include "X:/path/PingManager"
int main()
{
   /////  some code here....

   // We haven't instantiated a PingManager, but we want to use one now.
   // so we call GetInstance and get it to create one for us!
   PingManager::GetInstance()->run("This is a message!");

   ///// Some more code

   // This time around we've got an instance (created above!)
   PingManager::GetInstance()->run("This is another message");

   /////  More code
   return 0;
}

That may suit your needs a little better!

Let me know what you think!
Cheers for now,
Jas.

Thanks, but I dont think that the namespace option is right for this.

The point of having the list of "unknown" managers, is that for each message that is incoming (sockets) - it will iterate through the list of managers, giving them that data... If a manager see's its calling code (first thre chars in the incoming data) then it will operate, otherwise it will simply return and continue "waiting" for another peice of data.

The reason I give the data to every manager is so that mmore than one manager can use it... eg a PingManager, and a NetworkLoggingManager could both use the ping, but one would reply and the other would write a log about it...

The point of the code is that the actual networking code around the socket doesnt have to have an enoumous "if msg==this" etc... it can just get rid of the message.

What do you think?

Thanks

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.