如何在 C++ 中检查 vector 中的哪些对象

How to check which objects in vector in C++

嗯,Hospital 是 class,其中包含患者向量。 FemaleInFemaleOutMaleInMaleOut 源自 class 患者(基础 class)。那些 classes 有 toString 功能(方法)。我想做的是,在 Hospital class 中的 display 方法中,我只想显示 Outpatient 的父级 class FemaleOutMaleoutInpatientFemaleInMaleIn 的父级 class。根据我的想法,仅调用来自 Outpatient 的特定方法,我将不得不自动知道哪些对象在哪个向量索引中。有没有什么想法只为特定的 class 调用 toString,例如,FemaleInMaleIn,其中父 class 是 Inpatient。感谢您的任何帮助或建议。

void Hospital::determinePatientType()
{
    int selection;
    cout << endl;
    cout << "What is the patient type?" << endl;
    cout << "1. Female Inpatient" << endl;
    cout << "2. Female Outpatient" << endl;
    cout << "3. Male Inpatient" << endl;
    cout << "4. Male Outpatient" << endl;
    cout << endl;
    cin >> selection;

    switch(selection)
    {
    case 1:
        patients.push_back(new FemaleIn());
        cout << patients.back() << endl;
        patients[totalPatients]->enterPatientData();
        totalPatients++;
        break;
    case 2:
        patients.push_back(new FemaleOut());
        cout << patients.back() << endl;
        patients[totalPatients]->enterPatientData();
        totalPatients++;
        break;
    case 3:
        patients.push_back(new MaleIn());
        cout << patients.back() << endl;
        patients[totalPatients]->enterPatientData();
        totalPatients++;
        break;
    case 4:
        patients.push_back(new MaleOut());
        cout << patients.back() << endl;
        patients[totalPatients]->enterPatientData();
        totalPatients++;
        break;
    default:
        return;
    }

}

void Hospital::display(string type)
{


        cout << "Patient Name     Spouse Name    Sex    Patient Type    Unit/Appt. Date    Diagnosis" << endl;
        cout << "===================================================================================" << endl;

        if(type=="All")
        {
            for(int i=0;i<patients.size();i++)
            {
                patients[i]->toString();
            }

        }
        else if(type=="Outpatient")
        {
            for(int i=0;i<patients.size();i++)
            {
                patients[i]->toString();
            }
        }
        else
        {
            for(int i=0;i<patients.size();i++)
            {
                patients[i]->toString();
            }
        }

}

您可以使用 dynamic_cast 到某些 class 指针来检测给定实例是否属于 class:

    if (type == "Outpatient")
    {
        for(int i=0; i<patients.size(); ++i)
        {
            // try to cast parent class pointer to one of child class
            // if one is pointer to that child class p is not nullptr
            // otherwise p is nullptr
            Outpatient * p = dynamic_cast<Outpatient *>(patients[i]);

            if (p) {
                p->toString();
            }
        }
    }

为了简洁,您可以使用 Visitor pattern

访客模式实施:

#include <iostream>
#include <vector>
#include <string>
#include <functional>
#include <utility>

class AbstractDirectionPatientsDispatcher;
class AbstractGenderPatientDispatcher;

class Patient
{
public:
    virtual void accept(AbstractDirectionPatientsDispatcher &dispatcher) = 0;
    virtual void accept(AbstractGenderPatientDispatcher &dispatcher) = 0;

    std::string name;
};

class InPatient;
class OutPatient;

class AbstractDirectionPatientsDispatcher {
public:
    virtual void dispatch(InPatient &patient) = 0;
    virtual void dispatch(OutPatient &patient) = 0;
};

class FemalePatient;
class MalePatient;

class AbstractGenderPatientDispatcher {
public:
    virtual void dispatch(FemalePatient &patient) = 0;
    virtual void dispatch(MalePatient &patient) = 0;
};

template <typename PatientClass, typename Dispatcher>
class CRTPDispatchApplier : virtual public Patient
{
public:
    void accept(Dispatcher &dispatcher) override {
        dispatcher.dispatch(static_cast<PatientClass &>(*this));
    }
};

class InPatient : public CRTPDispatchApplier<InPatient, AbstractDirectionPatientsDispatcher>
{
};

class OutPatient : public CRTPDispatchApplier<OutPatient, AbstractDirectionPatientsDispatcher>
{
};

class FemalePatient : public CRTPDispatchApplier<FemalePatient, AbstractGenderPatientDispatcher>
{
};

class MalePatient : public CRTPDispatchApplier<MalePatient, AbstractGenderPatientDispatcher>
{
};


class InFemale : public FemalePatient, public InPatient
{
};

class OutFemale : public FemalePatient, public OutPatient
{
};

class InMale : public MalePatient, public InPatient
{
};

class OutMale : public MalePatient, public OutPatient
{
};

class DummyDirectionDispatecher : public AbstractDirectionPatientsDispatcher
{
public:
    void dispatch(InPatient & ) override {
    }

    void dispatch(OutPatient & ) override {
    }
};

class DummyGenderDispatcher : public AbstractGenderPatientDispatcher
{
public:
    void dispatch(FemalePatient &) override {
    }

    void dispatch(MalePatient &) override {
    }
};

template <typename Direction>
class DispatchByDirection : public DummyDirectionDispatecher
{
public:
    DispatchByDirection(std::function<void(Direction &)> action) :
        m_action(std::move(action))
    {}

    void dispatch(Direction & p) override {
        m_action(p);
    }

private:
    std::function<void(Direction &)> m_action;
};

template <typename Gender>
class DispatchByGender : public DummyGenderDispatcher
{
public:
    DispatchByGender(std::function<void(Gender &)> action) :
        m_action(std::move(action))
    {}

    void dispatch(Gender & p) override {
        m_action(p);
    }

private:
    std::function<void(Gender &)> m_action;
};

int main() {
    InFemale f1;
    OutFemale f2;
    InMale m1;
    OutMale m2;
    f1.name = "Eve";
    f2.name = "Alice";
    m1.name = "Bob";
    m2.name = "Charlie";

    std::vector<Patient *> patients;
    patients.push_back(&f1);
    patients.push_back(&f2);
    patients.push_back(&m1);
    patients.push_back(&m2);

    DispatchByDirection<InPatient> print_in_patients{[](InPatient &patient){
        std::cout << "in: " << patient.name << std::endl;
    }};

    for (auto p : patients) {
        p->accept(print_in_patients);
    }
    std::cout << std::endl;

    DispatchByDirection<OutPatient> print_out_patients{[](OutPatient &patient) {
        std::cout << "out: " << patient.name << std::endl;
    }};

    for (auto p : patients) {
        p->accept(print_out_patients);
    }
    std::cout << std::endl;

    DispatchByGender<FemalePatient> print_female{[](FemalePatient &patient) {
        std::cout << "female: " << patient.name << std::endl;
    }};

    for (auto p : patients) {
        p->accept(print_female);
    }
    std::cout << std::endl;

    DispatchByGender<MalePatient> print_male{[](MalePatient &patient) {
        std::cout << "male: " << patient.name << std::endl;
    }};

    for (auto p : patients) {
        p->accept(print_male);
    }
    std::cout << std::endl;
}

我认为这个问题可能与 How do I check if an object's type is a particular subclass in C++? 类似。

我会提出这样的建议:

Class Patient{
    virtual bool display(string filter);
};
Class OutPatient : Patient {
    bool display(string filter) override;
};
bool OutPatient::display(string filter) {
    if (filter != "OutPatient")
        return false;
    //Do stuff
    return true;
}
Class InPatient : Patient {
    bool display(string filter) override;
};
// You could just make this the default definition on display on Patient
bool InPatient::display(string filter) {
    return false;
}

然后:

void Hospital::display(string type)
{
    for(auto& patient: patients)
        patient->display(type);
}