在运行时从指针到基类获取对象的类型

Get object's type from pointer to base class at runtime

本文关键字:获取 取对象 类型 基类 运行时 指针      更新时间:2023-10-16

我正在使用一个类库,其中所有类都直接或间接地从基类Base派生并具有名称。库提供了通过名称搜索对象的功能,这将返回一个Base*

是否有任何方法可以找到返回对象的类型,而不像我在下面的例子中那样使用dynamic_cast s检查所有可能性?如果可能的话,我希望避免这种情况,因为派生类有模板形参,这就产生了相当多的可能性。

如果我至少能够在不知道模板类型的情况下找到类类型(T1T2,在下面的例子中),也会很好。像dynamic_cast<T1<i_dont_care>*> .

#include <iostream>
using namespace std;
class Base {
public:
    virtual ~Base() {}
};
template <typename T> class T1 : public Base {};
template <typename T> class T2 : public Base {};
Base *find_by_name() {
    return new T2<int>();
}
int main() {
    Base *b = find_by_name();
    if (T1<int> *p = dynamic_cast<T1<int>*>(b)) {
        cout << "T1<int>" << endl;
        // do something meaningful with p
    } else if (T1<double> *p = dynamic_cast<T1<double>*>(b))
        cout << "T1<double>" << endl;
    else if (T2<int> *p = dynamic_cast<T2<int>*>(b))
        cout << "T2<int>" << endl;
    else if (T2<double> *p = dynamic_cast<T2<double>*>(b))
        cout << "T2<double>" << endl;
    else
        cout << "unknown" << endl;
    delete b;
    return 0;
}

注意上面的例子是简化的,即。在每个if中,我会用p做一些有意义的事情。

我从一开始就意识到这是一个糟糕的设计,但是我被这个库困住了,我也没有办法改变它的实现。

有类似typeid http://en.cppreference.com/w/cpp/language/typeid的东西,它应用于多态表达将在运行时评估其类型表示。

下面的wiki示例:https://en.wikipedia.org/wiki/Run-time_type_information#dynamic_cast

#include <iostream> 
#include <typeinfo>    // for 'typeid'
class Person {
public:
   virtual ~Person() {}
};
class Employee : public Person {
};
int main() 
{
    Person person;
    Employee employee;
    Person* ptr = &employee;
    Person& ref = employee;
    // The string returned by typeid::name is implementation-defined
    // Person (statically known at compile-time)
    std::cout << typeid(person).name() << std::endl;   
    // Employee (statically known at compile-time)
    std::cout << typeid(employee).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) */
    std::cout << typeid(*ptr).name() << std::endl;     
    // Employee (references can also be polymorphic)        
    std::cout << typeid(ref).name() << std::endl;      
}

有一个typeid操作符,它返回一个std::type_info的实例,您可以通过它获得类型的名称。

不确定这是否对你有帮助。首先,返回的名称不能保证在不同实现之间是相同的。第二,一旦你知道了名字,你会怎么做?您可能会将其与预定义的名称进行比较,但这可能比一堆dynamic_cast慢。

如果没有内置在Base类中的类型支持或新的中间层次结构,dynamic_cast是您的最佳选择。实际上它会非常快(通常只有一条比较指令)。

中间层的意思是:

class Base {
public:
    virtual ~Base() {}
};
class T1Base : public Base {};
class T2Base : public Base {};
template <typename T> class T1 : public T1Base {};
template <typename T> class T2 : public T2Base {};
int main() {
    Base *b = find_by_name();
    if (dynamic_cast<T1Base*>(b))
        cout << "T1" << endl;
    else if (dynamic_cast<T2Base*>(b))
        cout << "T2" << endl;
    else
        cout << "unknown" << endl;
    delete b;
    return 0;
}