c++ - 使用 RTTI 从实现接口 c++ 的对象中获取类名
问题描述
我在 Animal 命名空间中有一个类 AnimalInterface:
namespace Animal
{
class AnimalInterface
{
public:
AnimalInterface() = default;
virtual ~AnimalInterface() = default;
virtual std::string makeSound() = 0;
};
}
假设我有 2 个从这个接口实现的类
class Dog : public AnimalInterface
{
public:
Dog() = default;
~Dog() = default;
std::string makeSound()
{
return "Bark";
}
};
class Cat : public AnimalInterface
{
public:
Cat() = default;
~Cat() = default;
std::string makeSound()
{
return "Meow";
}
};
现在我有一个类,我从中调用这些函数。我希望能够使用运行时类型信息从对象中获取动物的类名。
void AnimalSounds
{
list<unique_ptr<AnimalInterface>> animals;
animals.push_back(make_unique<Dog>());
animals.push_back(make_unique<Cat>());
for (const auto& animal : animals)
{
cout << typeid(animal).name() << " makes sound: " << animal->makeSound() << endl;
}
}
我希望输出是
Dog makes sound: Bark
Cat makes sound: Meow
相反,我得到以下
class std::unique_ptr<class Animal::AnimalInterface,struct std::default_delete<class Animal::AnimalInterface> > makes sound: Bark
class std::unique_ptr<class Animal::AnimalInterface,struct std::default_delete<class Animal::AnimalInterface> > makes sound: Meow
我该如何解决?谢谢!
解决方案
您需要取消引用指针。这样您就可以从它指向的对象而不是指针本身获取 RTTI 信息:
const auto& animal_ref = *animal;
cout << typeid(animal_ref).name() << " makes sound: " << animal->makeSound() << endl;
3Dog makes sound: Bark
3Cat makes sound: Meow
请注意,您仍然必须处理注释中描述的实现定义的名称。您可以为此使用库的 demangle 函数:
int status;
const auto& animal_ref = *animal;
const auto name = abi::__cxa_demangle(typeid(animal_ref).name(), 0, 0, &status);
cout << name << " makes sound: " << animal->makeSound() << endl;
Dog makes sound: Bark
Cat makes sound: Meow
除非为了更好地理解 RTTI 或出于调试目的而提出这个问题,否则我仍然强烈建议您重新考虑您的方法。这不是您的代码应该依赖的。
(是的,从技术上讲,即使是拆解可能还不够,并且名称可能会在调用之间发生变化。在我使用的实现中,这从未发生过。在我们谈论猫叫喵的时候,这更像是一种技术性比实际问题。)
推荐阅读
- python - 如何将元组 cursor.fetchall 列表转换为不同的格式
- c# - C# MVC 控制器返回拒绝访问
- cognos - Cognos Analytics 服务器安装文件未显示许可协议
- java - 列表大小仅在调试模式下捕获
- c - 需要帮助在 C 中逐个字符地读取文件
- swift - 在 Swift 中使用泛型实现装饰器模式
- makefile - Automake 不在子目录中生成 Makefile.in --- 但仅在 GitHub Actions 上
- node.js - conv.followup 在对话流中不工作
- docker - 如何使用任何自定义/插件 amp 文件为 Alfresco 6.2 创建自定义 docker 映像
- button - React:样式化组件加载按钮