C++ unique static id and class name with base class

前端 未结 3 1822
再見小時候
再見小時候 2021-01-22 20:32

Having class TaskBase, each derived class of it must have name and unique id.

The TaskBase is something like below:

class TaskB         


        
相关标签:
3条回答
  • 2021-01-22 20:57

    I suggest implementing pure virtual methods for obtaining the class name and ID in the base class. The descendants would need to provide the unique names and IDs.

    class TaskBase
    {
        public:
            virtual std::string  get_task_name(void) const = 0;
            virtual unsigned long get_task_id(void) const = 0;
    };
    

    I took @VoidStar's suggest a step further and put the names into a (single) common class:

    class TaskNames
    {
      protected:
        static std::string get_tas1_name();
    };
    
    class Task1: public TaskBase, public TaskNames
    {
    //...
    };
    
    0 讨论(0)
  • 2021-01-22 21:08
    class TaskBase
    {
    private:
        const void*  m_id;
        string m_name;
    
    public:
        TaskBase(const void* m_id, string m_name): m_id(m_id), m_name(m_name)
        {
        }
    
        const void* id() const
        {
            return m_id;
        }
    
        string name() const
        {
             return m_name;
        };
    };
    
    template< typename DERIVED >
    class TaskProxy: public TaskBase
    {
    public:   
        static const void* id()
        {
            //if you want to have for each object a unique id:
            //return reinterpret_cast<void*>(this);
            //just for each TaskProxy<????>:
            return reinterpret_cast<const void*>(typeid( DERIVED ).name());
        }
    
        static string name()
        {
            return typeid( DERIVED ).name();
        }
    
        TaskProxy(): TaskBase(id(), name()) {}
    };
    

    Usage:

    class MyTask1 : public TaskProxy< MyTask1 >
    {
    };
    
    class MyTask2 : public TaskProxy< MyTask2 >
    {
    };
    
    ...
    
    MyTask1 myTask1;
    TaskBase *baseA = &myTask1;
    MyTask2 myTask2;
    TaskBase *baseB = &myTask2;
    
    cout << "Name: " << baseA->name() << "  Id:" << baseA->id() << endl;
    cout << "Name: " << baseB->name() << "  Id:" << baseB->id() << endl;
    

    Which outputs this (with gcc 4.6):

    Name: 7MyTask1  Id:0x401228
    Name: 7MyTask2  Id:0x4011c0
    
    0 讨论(0)
  • 2021-01-22 21:12

    If you are following strictly standard C++, you may need to just bite the bullet and do some additional bookkeeping. Make an enum somewhere that stores all the classnames:

    enum ClassID {
        MYTASK1_CLASS,
        MYTASK2_CLASS
    };
    

    It doesn't take that long to add a new classId when you make a new class.

    I've done this before. It's sufficient for uniqueness to do what I describe above. But... if the enum values are set with a clever enough macro, you can encode the hierarchy of the classes, and implement dynamic cast and instanceof solely from the ClassID and a bitwise mask!

    0 讨论(0)
提交回复
热议问题