c++ - 检查一个对象的类是否派生自 C++ 中另一个对象的类

标签 c++ class object inheritance

如果我有对象 ab,我如何确定 a 的类是否继承自 b 的类?


背景:我有一个 C++ 库,我想为其编写一个 Python 绑定(bind)生成器。该库提供了一组从公共(public)基类派生的类。对于 Python 绑定(bind),我需要所有类的函数列表。我通过 nm -D myLibrary.so 得到了一个方法列表,但是缺少继承类的方法,例如风格

template<class WrappedClass>
class Wrapper: public WrappedClass {
  public:
    // ...
};

typedef Wrapper<ClassA> ClassB;

.所以我得到了像 ClassA 这样的类的所有功能,并且只想知道它们属于哪个 ClassB

我可以在运行时从库中获取所有可用类的名称列表,并且可以通过接受类名并提供该类型对象的工厂函数获取具有这些类型的对象。所以最后一 block 就是动态判断ClassB这样的类属于哪些类ClassA。因此问题。

PS:我原则上可以编写一个 C++ 代码生成器来生成测试代码,然后针对库进行编译以确定哪些类继承自哪些其他类。这将导致无法将我的代码与库一起编译但需要第二次编译的高成本。由于除了这个问题之外,我几乎可以解决这个问题,所以我非常希望有一个不同的解决方案。


PPS:有人告诉我在评论中使用 decltype。那行不通:

#include <iostream>
#include <type_traits>

struct A {};
struct B : A {};

int main() {
    A* a = new A();
    A* b = new B();
  std::cout << std::boolalpha;
  std::cout << "A, B: " << std::is_base_of<A,B>::value << std::endl;
  std::cout << "a, b: " << std::is_base_of<decltype(a),decltype(b)>::value << std::endl;
  std::cout << "*a, *b: " << std::is_base_of<decltype(*a),decltype(*b)>::value << std::endl;
  std::cout << "a., B: " << std::is_base_of<decltype(a),B>::value << std::endl;
  std::cout << "*a., B: " << std::is_base_of<decltype(*a),B>::value << std::endl;
  return 0;
}
}

产量

A, B: true
a, b: false
*a, *b: false
a., B: false
*a., B: false

PPPS:建议使用一个答案

std::is_base_of_v<std::decay_t<decltype(*a)>, std::decay_t<decltype(*b)>>

.我无法让它工作:

#include <iostream>
#include <type_traits>

struct A {};
struct B : A {};

int main() {
    A* a = new A();
    A* b = new B();
  std::cout << std::boolalpha;
  std::cout << "A, B: " << std::is_base_of<A,B>::value << std::endl;
  std::cout << "B, A: " << std::is_base_of<B,A>::value << std::endl;
  std::cout << "*a, *b: " << std::is_base_of<std::decay_t<decltype(*a)>, std::decay_t<decltype(*b)>>::value << std::endl;
  std::cout << "*b, *a: " << std::is_base_of<std::decay_t<decltype(*b)>, std::decay_t<decltype(*a)>>::value << std::endl;
  return 0;
}

产量:

A, B: true
B, A: false
*a, *b: true
*b, *a: true

最佳答案

If I got objects a and b, how do I determine if the class of a inherits from the class of b?

回答提出的问题,std::is_base_of:

std::is_base_of_v<std::decay_t<decltype(*a)>, std::decay_t<decltype(*b)>>

在您的示例中,ab 实际上不是对象,而是指向对象的指针,因此您必须取消引用才能获得对对象的引用,以 decltype 获取类型,然后使用 std::decay_t 移除引用和 const 限定。

在C++中,对象既有静态类型也有动态类型。 std::is_base_of 适用于静态类型。对于动态类型,dynamic_cast 会告诉您这些类型是否相关,但是没有标准查询只能回答一个动态类型是否是另一个动态类型的基础。对于用另一种语言包装,静态类型似乎是更有趣的类型,可以调用哪些成员函数。

但是,您解决实际问题的方法存在缺陷。使用 nm 确定类的成员函数名称不会告诉您这些名称的可访问性或如何解析重载。 std::is_base_of 将回答所问的问题,但如果基类不可访问或不明确,它将返回 true,在这种情况下,基类的成员函数不会返回直接应用于派生。

假设您不想手动维护绑定(bind),最好的方法是找到可以生成它们的工具(例如 swig)或编写这样的工具(例如使用 python clang 绑定(bind))。

关于c++ - 检查一个对象的类是否派生自 C++ 中另一个对象的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59167480/

相关文章:

c++ - 解决由于类之间的循环依赖而导致的构建错误

javascript - 为什么 JS for every in 函数给出太多?

c++ - 如何将两个_pd 转换为一个_ps?

c++ - 使用 find 和 substr 从我的输出中删除逗号

ruby - 是否可以更改 Ruby 对象的类?

javascript - 使用类附加到变量

javascript - 迭代对象属性,属性长度等于 JQuery 中的数字

arrays - TypeScript 对象作为 C# 中的字典类型

c++ - 如何使用 Clang 将链接器警告视为错误?

javascript - 在JavaScript中创建服务库,如何将一个文件中的函数导出到另一个文件中?