拥有类TaskBase
,每个派生类必须具有名称和唯一ID。
TaskBase
如下所示:
class TaskBase
{
public:
static const int id()
{
// return an unique id, for each object or derived class, HOW ??
}
static const string name()
{
// return class name for each derived class, HOW ??
// for example : "TaskBase" for this class
}
};
我的尝试是:
template <typename DERIVED>
class TaskBase
{
public:
static const int id()
{
static const int id = reinterpret_cast<int> (typeid (DERIVED).name());
return id;
}
static const string name()
{
static string n;
if (!n.size())
{
int status;
char *realname = abi::__cxa_demangle(typeid (DERIVED).name(), 0, 0, &status);
n = realname;
free(realname);
}
return n;
}
};
我已经阅读了this,但我需要能够拥有每个派生类的基指针,如下所示:
class MyTask1 : public TaskBase
{
};
MyTask1 myTask1, myTask2;
TaskBase *base = &myTask1;
答案 0 :(得分:3)
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()) {}
};
用法:
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;
哪个输出(使用gcc 4.6):
Name: 7MyTask1 Id:0x401228
Name: 7MyTask2 Id:0x4011c0
答案 1 :(得分:0)
如果您严格遵循标准C ++,您可能需要咬紧牙关并做一些额外的簿记。在某个存储所有类名的地方创建一个枚举:
enum ClassID {
MYTASK1_CLASS,
MYTASK2_CLASS
};
创建新类时,添加新的classId并不需要很长时间。
我以前做过这个。完成我上面描述的内容就足以实现独特性。但是......如果使用足够聪明的宏设置枚举值,则可以对类的层次结构进行编码,并仅使用ClassID和按位掩码实现动态强制转换和instanceof!
答案 2 :(得分:0)
我建议实现纯虚方法来获取基类中的类名和ID。后代需要提供唯一的名称和ID。
class TaskBase
{
public:
virtual std::string get_task_name(void) const = 0;
virtual unsigned long get_task_id(void) const = 0;
};
我把@VoidStar的建议更进一步,并将名字放入(单个)公共类中:
class TaskNames
{
protected:
static std::string get_tas1_name();
};
class Task1: public TaskBase, public TaskNames
{
//...
};