C++ 检查一个对象的类是否派生自C+中另一个对象的类+;
如果我得到了对象C++ 检查一个对象的类是否派生自C+中另一个对象的类+;,c++,class,object,inheritance,C++,Class,Object,Inheritance,如果我得到了对象a和b,我如何确定a类是否继承自b类 背景:我有一个C++库,我想编写一个Python绑定生成器。该库提供了一组从公共基类派生的类。对于Python绑定,我需要所有类的函数列表。我通过nm-D myLibrary获得了一个方法列表。因此,但缺少继承类的方法,例如以 模板 类包装器:公共包装类{ 公众: // ... }; typedef包装类b; 。所以我得到了类的所有函数,比如ClassA,我只想知道它们属于哪个ClassB 我可以在运行时从库中获取所有可用类的名称列表,并
a
和b
,我如何确定a
类是否继承自b
类
背景:我有一个C++库,我想编写一个Python绑定生成器。该库提供了一组从公共基类派生的类。对于Python绑定,我需要所有类的函数列表。我通过
nm-D myLibrary获得了一个方法列表。因此
,但缺少继承类的方法,例如以
模板
类包装器:公共包装类{
公众:
// ...
};
typedef包装类b;
。所以我得到了类的所有函数,比如ClassA
,我只想知道它们属于哪个ClassB
我可以在运行时从库中获取所有可用类的名称列表,并且可以通过接受类名并提供该类型对象的工厂函数获取具有这些类型的对象。所以最后一部分是动态地确定像ClassB
这样的类属于像ClassA
这样的类。因此,这是一个问题
PS:原则上我可以编写一个C++代码生成器,生成测试代码,然后对库编译,以确定哪些类继承哪些类。这将导致无法将代码与库一起编译,但需要进行第二次编译的高昂成本。由于除了这个问题之外,我还有几乎所有的东西可以绕过这个问题,我非常希望有一个不同的解决方案
PPS:我被告知在评论中使用
decltype
。这是行不通的:
#包括
#包括
结构A{};
结构B:A{};
int main(){
A*A=新的A();
A*b=新的b();
std::cout我发现的一个解决方案是使用安腾ABI。它主要来自。请注意,如果父类没有虚拟成员(尽管我不知道为什么),则这不起作用
因此:
#包括
#包括
#包括
#包括
布尔是祖先(const std::type_info&a,const std::type_info&b);
名称空间{
bool walk_tree(const_uucxxabiv1::uu si_class_type_info*si,const std::type_info&a){
返回si->\u base\u type==&a?true:is\u祖先(a,*si->\u base\u type);
}
bool walk_tree(const_cxxabiv1::_vmi_class_type_info*mi,const std::type_info&a){
对于(无符号整数i=0;i\u基数\u计数;++i){
if(是_祖先(a,*mi->_基本信息[i]。_基本类型))
返回true;
}
返回false;
}
}
布尔是祖先(const std::type_info&a,const std::type_info&b){
如果(a==b)
返回true;
常量cxxabiv1::uuu si_class_type_info*si=dynamic_cast(&b);
if(si)
返回步行树(si,a);
常量cxxabiv1::uuu vmi_class_type_info*mi=动态转换(&b);
如果(mi)
返回步行树(mi,a);
返回false;
}
类foo{virtualvoidf1(){}};
类栏:公共foo{virtualvoidf2(){};
abc类:公共条{virtualvoidf3(){};
int main(){
foo*myfoo=newfoo();
foo*mybar=newbar();
foo*myabc=newabc();
标准::cout
如果我得到了对象a和b,我如何确定a的类是否继承了b的类
在回答问题时,std::is_base_of
:
std::is_base_of_v<std::decay_t<decltype(*a)>, std::decay_t<decltype(*b)>>
std::是v的基础吗
在您的示例中,a
和b
实际上不是对象,而是指向对象的指针,因此您必须取消引用以获取对对象的引用,使用decltype
获取类型,然后使用std::decation\u t
删除引用和常量限定
<>在C++中,对象既有静态类型又有动态类型。<代码>:ST:: < /Cype >适用于静态类型。对于动态类型,<代码> DyrimCysCase<代码>将告诉您类型是否相关,但没有标准查询,只要动态类型的一个是另一个动态类型的基元,则只需回答。在另一种语言中,静态类型似乎是更有趣的类型,可以调用成员函数
然而,您解决实际问题的方法是有缺陷的。使用nm
确定类的成员函数名,并不能告诉您这些名称的可访问性,或者重载是如何解决的。并且std::is_base_of
将回答所问的问题,但如果基不可访问或biguous,在这种情况下,基的成员函数不直接应用于派生的
假设您不想手工维护绑定,最好的方法是找到一个可以生成它们的工具(例如swig)或编写这样的工具(例如使用python铿锵绑定)。您在找这个吗:@JerryJeremiah在我的理解中,std::is_base\u of
需要传递两个类,我只有两个对象。@2xB“我可以在运行时从库中获取所有可用类的名称列表"你能吗?你能演示一下你是如何做到的吗?直接使用标准库是不可能的,但如果你能枚举类型,那么就应该可以编一些东西。@2xB你可以使用。我认为如果使用typeid
,decltype
和is_base_of
,应该可以对所有的类型进行迭代并测试它们,但这是一个粗略的想法。如果您的对象没有vtable,这将不起作用。vtables通常仅为具有虚拟成员的对象发出(因为它们仅用于解析虚拟调用)。由于您的答案仅适用于静态类型,因此我的问题无法解决。我添加了另一条注释(PPPS)这是真的。我的回答是,动态类型不可能移植。但是,(a)我认为静态类型可能是包装时需要的。如果你有一个用其他语言包装的a,那就是我们
A, B: true
B, A: false
*a, *b: true
*b, *a: true
3bar 3foo
false
true
true
std::is_base_of_v<std::decay_t<decltype(*a)>, std::decay_t<decltype(*b)>>