Ben*_*igt 11
这可以用很少的代码完成:
template < class DERIVED >
class Foo
{
public:
static int s_id()
{
return reinterpret_cast<int>(&s_id);
}
};
Run Code Online (Sandbox Code Playgroud)
在现代C++中(假设您正在使用像gcc这样的最新编译器),您可以使用typeid关键字来获取至少在运行时提供基本类型信息的type_info对象 - 这是一个标准(然后是跨平台)功能.
我从维基百科中获取了示例并添加了模板/继承检查,它似乎运行良好,但我不确定int版本(这是一个hack利用编译器将在只读的某处具有类型名称的假设内存空间......这可能是一个错误的假设).
如果你可以在你的情况下使用它,那么字符串标识符对于跨平台识别似乎要好得多.它不是交叉编译兼容的,因为它给你的名称是标准的"实现定义" - 正如评论中所建议的那样.
完整的测试应用程序代码:
#include <iostream>
#include <typeinfo> //for 'typeid' to work
class Person
{
public:
// ... Person members ...
virtual ~Person() {}
};
class Employee : public Person
{
// ... Employee members ...
};
template< typename DERIVED >
class Test
{
public:
static int s_id()
{
// return id unique for DERIVED
// NOT SURE IT WILL BE REALLY UNIQUE FOR EACH CLASS!!
static const int id = reinterpret_cast<int>(typeid( DERIVED ).name());
return id;
}
static const char* s_name()
{
// return id unique for DERIVED
// ALWAYS VALID BUT STRING, NOT INT - BUT VALID AND CROSS-PLATFORM/CROSS-VERSION COMPATBLE
// AS FAR AS YOU KEEP THE CLASS NAME
return typeid( DERIVED ).name();
}
};
int wmain ()
{
Person person;
Employee employee;
Person *ptr = &employee;
std::cout << typeid(person).name() << std::endl; // Person (statically known at compile-time)
std::cout << typeid(employee).name() << std::endl; // Employee (statically known at compile-time)
std::cout << typeid(ptr).name() << std::endl; // Person * (statically known at compile-time)
std::cout << typeid(*ptr).name() << std::endl; // Employee (looked up dynamically at run-time
// because it is the dereference of a pointer to a polymorphic class)
Test<int> test;
std::cout << typeid(test).name() << std::endl;
std::cout << test.s_id() << std::endl;
std::cout << test.s_id() << std::endl;
std::cout << test.s_id() << std::endl;
std::cout << test.s_name() << std::endl;
Test< Person > test_person;
std::cout << test_person.s_name() << std::endl;
std::cout << test_person.s_id() << std::endl;
Test< Employee > test_employee;
std::cout << test_employee.s_name() << std::endl;
std::cout << test_employee.s_id() << std::endl;
Test< float > test_float;
std::cout << test_float.s_name() << std::endl;
std::cout << test_float.s_id() << std::endl;
std::cin.ignore();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
产出:
class Person
class Employee
class Person *
class Employee
class Test<int>
3462688
3462688
3462688
int
class Person
3421584
class Employee
3462504
float
3462872
Run Code Online (Sandbox Code Playgroud)
这至少在VC10Beta1和VC9上有效,应该适用于GCC.顺便说一句,要使用typeid(和dynamic_cast),您必须在编译器上允许运行时类型信息.默认情况下应该打开.在一些平台/编译器上(我正在考虑一些嵌入式硬件)RTTI没有打开因为它有成本,所以在某些极端情况下你必须找到一个更好的解决方案.
这就是我最终所做的。如果您有任何反馈(优点、缺点),请告诉我。
template < class DERIVED >
class Foo
{
public:
static const char* name(); // Derived classes will implement, simply
// returning their class name
static int s_id()
{
static const int id = Id_factory::get_instance()->get_id(name());
return id;
}
// ...
};
Run Code Online (Sandbox Code Playgroud)
本质上,id 将在进行字符串比较而不是指针比较后分配。这在速度方面并不理想,但我将 id 设置为静态常量,因此只需为每个 DERIVED 计算一次。
| 归档时间: |
|
| 查看次数: |
19128 次 |
| 最近记录: |