是否可以在 C++ 中将名称附加到运行时类
Is it possible to attach a name to a runtime class in C++?
我有一个类的层次结构,基类具有打印类名的功能:
#include <iostream>
using namespace std;
class base
{
public:
virtual void print_name() { cout << typeid(*this).name() << endl; };
};
class derived1 : public base { };
class derived2 : public base { };
int main ()
{
base Base;
Base.print_name();
derived1 Derived1;
Derived1.print_name();
derived2 Derived2;
Derived2.print_name();
}
上述输出为
class base
class derived1
class derived2
事实上,这取决于平台。
是否有一种或多或少的标准方法可以将一些唯一的名称"附加"到每个类,以便它可以用于printname()
使所有平台的输出相同(并且独立于对真实类名所做的任何更改)?
当然:
class base {
public:
virtual char const *name() const { return "base"; }
};
class derived1 : public base {
public:
virtual char const *name() const { return "derived1"; }
};
但是,如果不重写类中的name
,则其名称将是其超类的名称。这可能是错误或功能,具体取决于您的用例。如果这是一个错误,那么你可以添加一些运行时检查,以确保该方法被覆盖:
virtual char const *name() const {
if (typeid(*this) != typeid(base))
throw std::logic_error("name() not overridden");
return "base";
}
但是,您必须在必须重写的每个name
实现中重复此检查。
您可以有效地使用type_info
来实现此目的。
type_info
支持符合弱顺序的before
方法,只要提供用户提供的谓词,它就允许在std::map
(例如)中使用。
struct TypeInfoLess {
bool operator()(std::type_info const* lhs, std::type_info const* rhs) const {
return lhs->before(rhs);
}
};
struct AdditionalTypeInfo {
std::string name;
};
typedef std::map<std::type_info const*, AdditionalTypeInfo, TypeInfoLess> TypeInfoMap;
然后,您可以添加/搜索类型:
template <typename T>
void add(TypeInfoMap& map, T const& t, AdditionalTypeInfo const& ati) {
map[&typeid(t)] = ati;
}
template <typename T>
AdditionalTypeInfo const* find(TypeInfoMap const& map, T const& t) {
TypeInfoMap::const_iterator it = map.find(&typeid(t));
if (it == map.end()) { return 0; }
return &it->second;
}
int main() {
TypeInfoMap timap;
add(timap, timap, { "TypeInfoMap" });
if (AdditionalTypeInfo const* const ati = find(timap, timap)) {
std::cout << ati->name << "n";
}
}
注意:然后,您有责任将您可能想要的每种类型添加到地图中。
您可以使用模板函数(或特征类)来获取名称:
template<typename T> const char * ClassName(T const * objPtr);
template<> const char * ClassName<derived1>(derived1 const *objPtr) { return "derived1"; }
template<> const char * ClassName<derived2>(derived2 const *objPtr) { return "derived2"; }
(此处函数参数仅用于模板参数匹配)。在调用代码时,您可以将指针投射到特定的类并使用类名
derived1 * pDerived = static_cast<derived1*>(pPointer);
cout << ClassName(pDerived);
但是,这都是编译时,您将需要一些机制(如 GUID)在运行时标识类(将其强制转换为右指针类型)。如果你的类没有,你不能修改它们,那么我就帮不了你;(但是,您可以使用特征技术来本地化依赖于平台的类型选择代码。
相关文章:
- CMake-按正确顺序将项目与C运行时对象文件链接
- 我在c++代码中生成了一个运行时#3异常
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- 删除指向指针的指针是运行时错误吗
- 如何用参数值调用函数(仅在运行时已知)
- 为什么即使使用-cudart-static进行编译,库用户仍然需要链接到cuda运行时
- 是否可以在编译时初始化数组,以便在运行时不会花费时间?
- c++中的指针和运行时错误
- 在运行时处理类型擦除的数据-如何不重新发明轮子
- 有没有一种方法可以测量c++程序的运行时内存使用情况
- 建议在运行时将带有类实例的列表从c++导入qml
- 无法理解此 return 语句的功能,没有它就会发生运行时错误
- 如何在GTK程序运行时禁用屏幕保护程序/电源管理/屏幕消隐
- 在同一模拟中使用静脉和静脉_ inet内容时出现运行时错误
- 读取文件时运行时的未知行为
- 函数在Windows或Linux上运行时表现不同
- 在声明中合并两个常量"std::set"(不是在运行时)
- AWS Lambda C++运行时权限被拒绝
- 通过switch和static_cast访问多态对象的运行时类型
- 如何修复 Onnx运行时会话>运行问题?