比较从父类继承但存储在父类的向量中的类的对象类型

Compare the object type of a class that inherits from a parent class but stored in vector of parent class

本文关键字:父类 向量 对象 类型 继承 存储 比较      更新时间:2023-10-16

我想比较从父类继承并存储在父类向量中的子类的对象类型,如下所示:

#include <string>
#include <iostream>
#include <vector>
#include <typeinfo>
using namespace std;
class Agent{
public:
    Agent(string nam){ name = nam; }
    ~Agent();
protected:
    string name;
};
class Human :public Agent{
public:
    Human(string nam, int a):Agent(nam){ age = a; }
    ~Human();
protected:
    int age;
};
int main(){
    vector<Agent*> agents;
    Agent* agent=new Agent("ask");
    Human* human=new Human("ask2",18);
    Agent* agent2=new Human("AgentAsk",20);
    agents.push_back(agent);
    agents.push_back(human);
    agents.push_back(agent2);
    cout << (typeid(agents[1]) == typeid(Agent*)) << endl; /// True
    cout << (typeid(agents[1]) == typeid(Human*)) << endl; /// I expect it to be true but its false
    cout << (typeid(agents[1]) != typeid(Agent*)) << endl; /// False
    return 0;
}

我需要帮助才能获得正确的结果。
我搜索了它,但找不到合适的解决方案和解释。
请尽可能多地解释您的代码。

您可以为类使用类型特征,但是如果您需要一个简单的(也许是快速且肮脏的)解决方案,则可以执行以下操作:

#include <string>
#include <iostream>
#include <vector>
#include <typeinfo>
using namespace std;
class Agent{
public:
    static const string TYPE;
    explicit Agent(const string& nam) : name(nam) {}
    virtual ~Agent(){}
    virtual string type() const {
        return TYPE;
    }
protected:
    string name;
};
const string Agent::TYPE = "Agent";
class Human :public Agent {
public:
    static const string TYPE;
    Human(const string& nam, int a):Agent(nam), age(a) {}
    ~Human(){}
    virtual string type() const {
        return TYPE;
    }
protected:
    int age;
};
const string Human::TYPE = "Human";

int main(){
    vector<Agent*> agents;
    Agent* agent=new Agent("ask");
    Human* human=new Human("ask2",18);
    Agent* agent2=new Human("AgentAsk",20);
    agents.push_back(agent);
    agents.push_back(human);
    agents.push_back(agent2);
    for(auto agent : agents) {
        cout << agent->type() << " ";
        cout << boolalpha << (agent->type() == Agent::TYPE) << endl;
    }
    //free up memory allocated using new
    // or just use smart pointers
    return 0;
}

最好定义一个抽象类,并将抽象(如type()方法)向上移动,并将其他详细信息向下移动到派生类。

下面是在运行时区分层次结构中的类型的可能方法(根据 OP 的要求,代码中的注释):

#include<vector>
#include<cassert>
// This is a simple class that acts as a counter
struct Cnt {
    static int cnt;
};
int Cnt::cnt = 0;
// A template class helps us to differentiate
// the types and to give them a set of  values
// that identify the actual types at runtime
template<typename T>
struct Type: private Cnt {
    static const int type;
};
template<typename T>
const int Type<T>::type = Cnt::cnt++;
// The Agent offers a virtual method that
// returns a numeric identifier of the type.
// The above mentioned classes are used
// to generate an unique value for this type.
class Agent {
public:
    virtual int type() const {
        return Type<Agent>::type;
    }
};
// If you want Human to have its own
// numeric identifier, you can simply override
// the inherited method and return a different
// type.
// Using the Type class is still the right
// solution. It assures that the returned type 
// won't collide with the ones generated so
// far.
class Human: public Agent {
public:
    int type() const override {
         return Type<Human>::type;
    }
};
int main() {
    std::vector<Agent*> vec;
    vec.push_back(new Agent);
    vec.push_back(new Human);
    assert(vec[0]->type() == Type<Agent>::type);
    assert(vec[0]->type() != Type<Human>::type);
    assert(vec[1]->type() == Type<Human>::type);
    assert(vec[1]->type() != Type<Agent>::type);
}

这是非常具有侵入性的,但是如果您愿意,您也可以决定不给孩子不同的类型。

关于typeid的说明 .
从这里您可以找到:

不能保证同一类型的 typeid 表达式的所有计算都会引用同一个std::type_info实例

即使使用不同类型的产品,您也不会得到保证。无论如何,您每次都在同一类型上使用 typeof 运算符。

你创建了一个Agent*向量,所以(typeid(agents[1]) == typeid(Human*))是假的,因为agents[1]是一个Agent,而不是一个Human